{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Use Soft Actor-Critic with Auto $\\alpha$ Tuning to Play LunarLanderContinuous-v2\n",
    "\n",
    "PyTorch version"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "\n",
    "import sys\n",
    "import imp\n",
    "import logging\n",
    "import itertools\n",
    "import copy\n",
    "\n",
    "import numpy as np\n",
    "np.random.seed(0)\n",
    "import pandas as pd\n",
    "import gym\n",
    "import matplotlib.pyplot as plt\n",
    "import torch\n",
    "torch.manual_seed(0)\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "import torch.distributions as distributions\n",
    "\n",
    "imp.reload(logging)\n",
    "logging.basicConfig(level=logging.DEBUG,\n",
    "        format='%(asctime)s [%(levelname)s] %(message)s',\n",
    "        stream=sys.stdout, datefmt='%H:%M:%S')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "19:46:28 [INFO] env: <LunarLanderContinuous<LunarLanderContinuous-v2>>\n",
      "19:46:28 [INFO] action_space: Box(-1.0, 1.0, (2,), float32)\n",
      "19:46:28 [INFO] observation_space: Box(-inf, inf, (8,), float32)\n",
      "19:46:28 [INFO] reward_range: (-inf, inf)\n",
      "19:46:28 [INFO] metadata: {'render.modes': ['human', 'rgb_array'], 'video.frames_per_second': 50}\n",
      "19:46:28 [INFO] _max_episode_steps: 1000\n",
      "19:46:28 [INFO] _elapsed_steps: None\n"
     ]
    }
   ],
   "source": [
    "env = gym.make(\"LunarLanderContinuous-v2\")\n",
    "env.seed(0)\n",
    "for key in vars(env):\n",
    "    logging.info('%s: %s', key, vars(env)[key])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class DQNReplayer:\n",
    "    def __init__(self, capacity):\n",
    "        self.memory = pd.DataFrame(index=range(capacity),\n",
    "                columns=['state', 'action', 'reward', 'next_state', 'done'])\n",
    "        self.i = 0\n",
    "        self.count = 0\n",
    "        self.capacity = capacity\n",
    "\n",
    "    def store(self, *args):\n",
    "        self.memory.loc[self.i] = args\n",
    "        self.i = (self.i + 1) % self.capacity\n",
    "        self.count = min(self.count + 1, self.capacity)\n",
    "\n",
    "    def sample(self, size):\n",
    "        indices = np.random.choice(self.count, size=size)\n",
    "        return (np.stack(self.memory.loc[indices, field]) for field in\n",
    "                self.memory.columns)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class SACAgent:\n",
    "    def __init__(self, env):\n",
    "        state_dim = env.observation_space.shape[0]\n",
    "        self.action_dim = env.action_space.shape[0]\n",
    "        self.action_low = env.action_space.low\n",
    "        self.action_high = env.action_space.high\n",
    "        self.gamma = 0.99\n",
    "\n",
    "        self.replayer = DQNReplayer(100000)\n",
    "\n",
    "        # create alpha\n",
    "        self.target_entropy = -self.action_dim\n",
    "        self.ln_alpha = torch.zeros(1, requires_grad=True)\n",
    "        self.alpha_optimizer = optim.Adam([self.ln_alpha,], lr=0.0003)\n",
    "\n",
    "        # create actor\n",
    "        self.actor_net = self.build_net(input_size=state_dim,\n",
    "                hidden_sizes=[256, 256], output_size=self.action_dim*2,\n",
    "                output_activator=nn.Tanh())\n",
    "        self.actor_optimizier = optim.Adam(self.actor_net.parameters(), lr=0.0003)\n",
    "\n",
    "        # create V critic\n",
    "        self.v_evaluate_net = self.build_net(input_size=state_dim,\n",
    "                hidden_sizes=[256, 256])\n",
    "        self.v_target_net = copy.deepcopy(self.v_evaluate_net)\n",
    "        self.v_loss = nn.MSELoss()\n",
    "        self.v_optimizer = optim.Adam(self.v_evaluate_net.parameters(), lr=0.0003)\n",
    "\n",
    "        # create Q critic\n",
    "        self.q0_net = self.build_net(input_size=state_dim+self.action_dim,\n",
    "                hidden_sizes=[256, 256])\n",
    "        self.q1_net = self.build_net(input_size=state_dim+self.action_dim,\n",
    "                hidden_sizes=[256, 256])\n",
    "        self.q0_loss = nn.MSELoss()\n",
    "        self.q1_loss = nn.MSELoss()\n",
    "        self.q0_optimizer = optim.Adam(self.q0_net.parameters(), lr=0.0003)\n",
    "        self.q1_optimizer = optim.Adam(self.q1_net.parameters(), lr=0.0003)\n",
    "\n",
    "    def build_net(self, input_size, hidden_sizes, output_size=1,\n",
    "            output_activator=None):\n",
    "        layers = []\n",
    "        for input_size, output_size in zip(\n",
    "                [input_size,] + hidden_sizes, hidden_sizes + [output_size,]):\n",
    "            layers.append(nn.Linear(input_size, output_size))\n",
    "            layers.append(nn.ReLU())\n",
    "        layers = layers[:-1]\n",
    "        if output_activator:\n",
    "            layers.append(output_activator)\n",
    "        net = nn.Sequential(*layers)\n",
    "        return net\n",
    "\n",
    "    def get_action_ln_prob_tensors(self, state_tensor):\n",
    "        mean_ln_std_tensor = self.actor_net(state_tensor)\n",
    "        mean_tensor, ln_std_tensor = torch.split(mean_ln_std_tensor,\n",
    "                self.action_dim, dim=-1)\n",
    "        if self.mode == 'train':\n",
    "            std_tensor = torch.exp(ln_std_tensor)\n",
    "            normal_dist = distributions.Normal(mean_tensor, std_tensor)\n",
    "            rsample_tensor = normal_dist.rsample()\n",
    "            action_tensor = torch.tanh(rsample_tensor)\n",
    "            ln_prob_tensor = normal_dist.log_prob(rsample_tensor) - \\\n",
    "                    torch.log1p(1e-6 - action_tensor.pow(2))\n",
    "            ln_prob_tensor = ln_prob_tensor.sum(-1, keepdim=True)\n",
    "        else:\n",
    "            action_tensor = torch.tanh(mean_tensor)\n",
    "            ln_prob_tensor = torch.ones_like(action_tensor)\n",
    "        return action_tensor, ln_prob_tensor\n",
    "\n",
    "    def reset(self, mode):\n",
    "        self.mode = mode\n",
    "        if self.mode == 'train':\n",
    "            self.trajectory = []\n",
    "\n",
    "    def step(self, observation, reward, done):\n",
    "        if self.mode == 'train' and self.replayer.count < 5000:\n",
    "            action = np.random.uniform(self.action_low, self.action_high)\n",
    "        else:\n",
    "            state_tensor = torch.as_tensor(observation).unsqueeze(0)\n",
    "            action_tensor, _ = self.get_action_ln_prob_tensors(state_tensor)\n",
    "            action = action_tensor[0].detach().numpy()\n",
    "        if self.mode == 'train':\n",
    "            self.trajectory += [observation, reward, done, action]\n",
    "            if len(self.trajectory) >= 8:\n",
    "                state, _, _, act, next_state, reward, done, _ = \\\n",
    "                        self.trajectory[-8:]\n",
    "                self.replayer.store(state, act, reward, next_state, done)\n",
    "            if self.replayer.count >= 128:\n",
    "                self.learn()\n",
    "        return action\n",
    "\n",
    "    def close(self):\n",
    "        pass\n",
    "\n",
    "    def update_net(self, target_net, evaluate_net, learning_rate=0.005):\n",
    "        for target_param, evaluate_param in zip(\n",
    "                target_net.parameters(), evaluate_net.parameters()):\n",
    "            target_param.data.copy_(learning_rate * evaluate_param.data\n",
    "                    + (1 - learning_rate) * target_param.data)\n",
    "\n",
    "    def learn(self):\n",
    "        states, actions, rewards, next_states, dones = self.replayer.sample(128)\n",
    "        state_tensor = torch.as_tensor(states, dtype=torch.float)\n",
    "        action_tensor = torch.as_tensor(actions, dtype=torch.float)\n",
    "        reward_tensor = torch.as_tensor(rewards, dtype=torch.float)\n",
    "        next_state_tensor = torch.as_tensor(next_states, dtype=torch.float)\n",
    "        done_tensor = torch.as_tensor(dones, dtype=torch.float)\n",
    "\n",
    "        # train alpha\n",
    "        act_tensor, ln_prob_tensor = self.get_action_ln_prob_tensors(state_tensor)\n",
    "        alpha_loss_tensor = (-self.ln_alpha * (ln_prob_tensor +\n",
    "                self.target_entropy).detach()).mean()\n",
    "\n",
    "        self.alpha_optimizer.zero_grad()\n",
    "        alpha_loss_tensor.backward()\n",
    "        self.alpha_optimizer.step()\n",
    "\n",
    "        # train Q critic\n",
    "        states_action_tensor = torch.cat((state_tensor, action_tensor), dim=-1)\n",
    "        q0_tensor = self.q0_net(states_action_tensor)\n",
    "        q1_tensor = self.q1_net(states_action_tensor)\n",
    "        next_v_tensor = self.v_target_net(next_state_tensor)\n",
    "        q_target = reward_tensor.unsqueeze(1) + \\\n",
    "                self.gamma * next_v_tensor * (1. - done_tensor.unsqueeze(1))\n",
    "        q0_loss_tensor = self.q0_loss(q0_tensor, q_target.detach())\n",
    "        q1_loss_tensor = self.q1_loss(q1_tensor, q_target.detach())\n",
    "\n",
    "        self.q0_optimizer.zero_grad()\n",
    "        q0_loss_tensor.backward()\n",
    "        self.q0_optimizer.step()\n",
    "\n",
    "        self.q1_optimizer.zero_grad()\n",
    "        q1_loss_tensor.backward()\n",
    "        self.q1_optimizer.step()\n",
    "\n",
    "        # train V critic\n",
    "        state_act_tensor = torch.cat((state_tensor, act_tensor), dim=-1)\n",
    "        v_pred_tensor = self.v_evaluate_net(state_tensor)\n",
    "        q0_pred_tensor = self.q0_net(state_act_tensor)\n",
    "        q1_pred_tensor = self.q1_net(state_act_tensor)\n",
    "        q_pred_tensor = torch.min(q0_pred_tensor, q1_pred_tensor)\n",
    "        alpha_tensor = self.ln_alpha.exp()\n",
    "        v_target_tensor = q_pred_tensor - alpha_tensor * ln_prob_tensor\n",
    "        v_loss_tensor = self.v_loss(v_pred_tensor, v_target_tensor.detach())\n",
    "\n",
    "        self.v_optimizer.zero_grad()\n",
    "        v_loss_tensor.backward()\n",
    "        self.v_optimizer.step()\n",
    "\n",
    "        self.update_net(self.v_target_net, self.v_evaluate_net)\n",
    "\n",
    "        # train actor\n",
    "        advantage_tensor = q_pred_tensor - v_pred_tensor.detach()\n",
    "        actor_loss_tensor = (alpha_tensor * ln_prob_tensor - advantage_tensor).mean()\n",
    "\n",
    "        self.actor_optimizier.zero_grad()\n",
    "        actor_loss_tensor.backward()\n",
    "        self.actor_optimizier.step()\n",
    "\n",
    "\n",
    "agent = SACAgent(env)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "19:46:28 [INFO] ==== train ====\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "19:46:29 [DEBUG] train episode 0: reward = -112.08, steps = 140\n",
      "19:46:35 [DEBUG] train episode 1: reward = -281.50, steps = 159\n",
      "19:46:41 [DEBUG] train episode 2: reward = -234.58, steps = 137\n",
      "19:46:48 [DEBUG] train episode 3: reward = -158.37, steps = 187\n",
      "19:46:55 [DEBUG] train episode 4: reward = -298.07, steps = 170\n",
      "19:46:58 [DEBUG] train episode 5: reward = -335.86, steps = 75\n",
      "19:47:02 [DEBUG] train episode 6: reward = -426.55, steps = 108\n",
      "19:47:06 [DEBUG] train episode 7: reward = -149.63, steps = 111\n",
      "19:47:09 [DEBUG] train episode 8: reward = -69.06, steps = 73\n",
      "19:47:13 [DEBUG] train episode 9: reward = -271.07, steps = 96\n",
      "19:47:17 [DEBUG] train episode 10: reward = -408.78, steps = 105\n",
      "19:47:23 [DEBUG] train episode 11: reward = -102.08, steps = 137\n",
      "19:47:28 [DEBUG] train episode 12: reward = -390.09, steps = 145\n",
      "19:47:33 [DEBUG] train episode 13: reward = -408.79, steps = 107\n",
      "19:47:35 [DEBUG] train episode 14: reward = -92.82, steps = 69\n",
      "19:47:39 [DEBUG] train episode 15: reward = -352.78, steps = 87\n",
      "19:47:42 [DEBUG] train episode 16: reward = -234.04, steps = 89\n",
      "19:47:47 [DEBUG] train episode 17: reward = -250.68, steps = 127\n",
      "19:47:52 [DEBUG] train episode 18: reward = -250.59, steps = 119\n",
      "19:47:58 [DEBUG] train episode 19: reward = -320.67, steps = 152\n",
      "19:48:01 [DEBUG] train episode 20: reward = -373.46, steps = 81\n",
      "19:48:05 [DEBUG] train episode 21: reward = -88.18, steps = 83\n",
      "19:48:08 [DEBUG] train episode 22: reward = -36.75, steps = 80\n",
      "19:48:12 [DEBUG] train episode 23: reward = -139.52, steps = 97\n",
      "19:48:16 [DEBUG] train episode 24: reward = -352.28, steps = 106\n",
      "19:48:21 [DEBUG] train episode 25: reward = -111.02, steps = 121\n",
      "19:48:25 [DEBUG] train episode 26: reward = -173.87, steps = 104\n",
      "19:48:29 [DEBUG] train episode 27: reward = -357.54, steps = 101\n",
      "19:48:34 [DEBUG] train episode 28: reward = -187.84, steps = 125\n",
      "19:48:42 [DEBUG] train episode 29: reward = -259.05, steps = 213\n",
      "19:48:47 [DEBUG] train episode 30: reward = -189.09, steps = 113\n",
      "19:48:51 [DEBUG] train episode 31: reward = -233.59, steps = 106\n",
      "19:48:55 [DEBUG] train episode 32: reward = -447.59, steps = 104\n",
      "19:49:01 [DEBUG] train episode 33: reward = -298.22, steps = 157\n",
      "19:49:06 [DEBUG] train episode 34: reward = -312.16, steps = 106\n",
      "19:49:10 [DEBUG] train episode 35: reward = -99.37, steps = 114\n",
      "19:49:15 [DEBUG] train episode 36: reward = -402.26, steps = 115\n",
      "19:49:19 [DEBUG] train episode 37: reward = -280.93, steps = 104\n",
      "19:49:23 [DEBUG] train episode 38: reward = -77.80, steps = 104\n",
      "19:49:27 [DEBUG] train episode 39: reward = -194.40, steps = 82\n",
      "19:49:32 [DEBUG] train episode 40: reward = -260.22, steps = 120\n",
      "19:49:37 [DEBUG] train episode 41: reward = -267.42, steps = 117\n",
      "19:49:42 [DEBUG] train episode 42: reward = -116.98, steps = 134\n",
      "19:50:01 [DEBUG] train episode 43: reward = -77.35, steps = 443\n",
      "19:50:28 [DEBUG] train episode 44: reward = -150.93, steps = 618\n",
      "19:50:36 [DEBUG] train episode 45: reward = -331.62, steps = 193\n",
      "19:51:21 [DEBUG] train episode 46: reward = -131.62, steps = 1000\n",
      "19:52:08 [DEBUG] train episode 47: reward = -91.34, steps = 1000\n",
      "19:52:54 [DEBUG] train episode 48: reward = -96.93, steps = 1000\n",
      "19:53:38 [DEBUG] train episode 49: reward = -35.61, steps = 1000\n",
      "19:53:43 [DEBUG] train episode 50: reward = 23.34, steps = 130\n",
      "19:53:47 [DEBUG] train episode 51: reward = -60.30, steps = 106\n",
      "19:54:32 [DEBUG] train episode 52: reward = -41.86, steps = 1000\n",
      "19:55:18 [DEBUG] train episode 53: reward = -28.60, steps = 1000\n",
      "19:56:03 [DEBUG] train episode 54: reward = -24.83, steps = 1000\n",
      "19:56:50 [DEBUG] train episode 55: reward = -35.99, steps = 1000\n",
      "19:57:21 [DEBUG] train episode 56: reward = -127.96, steps = 695\n",
      "19:58:09 [DEBUG] train episode 57: reward = 45.12, steps = 1000\n",
      "19:58:31 [DEBUG] train episode 58: reward = -68.16, steps = 509\n",
      "19:59:20 [DEBUG] train episode 59: reward = -36.09, steps = 1000\n",
      "20:00:07 [DEBUG] train episode 60: reward = -27.97, steps = 1000\n",
      "20:00:54 [DEBUG] train episode 61: reward = -59.16, steps = 1000\n",
      "20:01:41 [DEBUG] train episode 62: reward = -43.61, steps = 1000\n",
      "20:02:29 [DEBUG] train episode 63: reward = -6.84, steps = 1000\n",
      "20:03:12 [DEBUG] train episode 64: reward = -26.66, steps = 1000\n",
      "20:03:58 [DEBUG] train episode 65: reward = 4.85, steps = 1000\n",
      "20:04:42 [DEBUG] train episode 66: reward = -29.84, steps = 1000\n",
      "20:05:29 [DEBUG] train episode 67: reward = -29.38, steps = 1000\n",
      "20:06:14 [DEBUG] train episode 68: reward = -17.47, steps = 1000\n",
      "20:07:00 [DEBUG] train episode 69: reward = -47.46, steps = 1000\n",
      "20:07:46 [DEBUG] train episode 70: reward = -55.57, steps = 1000\n",
      "20:08:31 [DEBUG] train episode 71: reward = -8.04, steps = 1000\n",
      "20:09:17 [DEBUG] train episode 72: reward = -73.72, steps = 1000\n",
      "20:10:01 [DEBUG] train episode 73: reward = -10.96, steps = 1000\n",
      "20:10:45 [DEBUG] train episode 74: reward = -47.67, steps = 1000\n",
      "20:11:28 [DEBUG] train episode 75: reward = -22.44, steps = 1000\n",
      "20:12:10 [DEBUG] train episode 76: reward = -63.48, steps = 1000\n",
      "20:12:58 [DEBUG] train episode 77: reward = -60.47, steps = 1000\n",
      "20:13:42 [DEBUG] train episode 78: reward = -30.89, steps = 1000\n",
      "20:14:28 [DEBUG] train episode 79: reward = -46.45, steps = 1000\n",
      "20:15:13 [DEBUG] train episode 80: reward = -65.07, steps = 1000\n",
      "20:16:02 [DEBUG] train episode 81: reward = -54.58, steps = 1000\n",
      "20:16:46 [DEBUG] train episode 82: reward = -17.76, steps = 1000\n",
      "20:17:32 [DEBUG] train episode 83: reward = -50.70, steps = 1000\n",
      "20:18:17 [DEBUG] train episode 84: reward = 5.01, steps = 1000\n",
      "20:19:02 [DEBUG] train episode 85: reward = -37.81, steps = 1000\n",
      "20:19:48 [DEBUG] train episode 86: reward = -26.73, steps = 1000\n",
      "20:20:35 [DEBUG] train episode 87: reward = -30.88, steps = 1000\n",
      "20:21:20 [DEBUG] train episode 88: reward = -38.17, steps = 1000\n",
      "20:22:03 [DEBUG] train episode 89: reward = -26.52, steps = 1000\n",
      "20:22:47 [DEBUG] train episode 90: reward = -18.60, steps = 1000\n",
      "20:23:33 [DEBUG] train episode 91: reward = -15.99, steps = 1000\n",
      "20:24:18 [DEBUG] train episode 92: reward = -23.18, steps = 1000\n",
      "20:25:07 [DEBUG] train episode 93: reward = -52.97, steps = 1000\n",
      "20:25:54 [DEBUG] train episode 94: reward = -24.18, steps = 1000\n",
      "20:26:40 [DEBUG] train episode 95: reward = -34.57, steps = 1000\n",
      "20:27:25 [DEBUG] train episode 96: reward = 10.68, steps = 1000\n",
      "20:28:09 [DEBUG] train episode 97: reward = -7.83, steps = 1000\n",
      "20:28:58 [DEBUG] train episode 98: reward = 25.42, steps = 1000\n",
      "20:29:47 [DEBUG] train episode 99: reward = 8.97, steps = 1000\n",
      "20:30:34 [DEBUG] train episode 100: reward = 0.51, steps = 1000\n",
      "20:31:21 [DEBUG] train episode 101: reward = -8.01, steps = 1000\n",
      "20:32:08 [DEBUG] train episode 102: reward = -16.60, steps = 1000\n",
      "20:32:55 [DEBUG] train episode 103: reward = 1.96, steps = 1000\n",
      "20:33:40 [DEBUG] train episode 104: reward = -86.77, steps = 1000\n",
      "20:34:26 [DEBUG] train episode 105: reward = -14.59, steps = 1000\n",
      "20:35:15 [DEBUG] train episode 106: reward = -22.59, steps = 1000\n",
      "20:36:02 [DEBUG] train episode 107: reward = -74.47, steps = 1000\n",
      "20:36:16 [DEBUG] train episode 108: reward = -115.62, steps = 327\n",
      "20:37:01 [DEBUG] train episode 109: reward = -29.51, steps = 1000\n",
      "20:37:48 [DEBUG] train episode 110: reward = 3.74, steps = 1000\n",
      "20:38:35 [DEBUG] train episode 111: reward = 2.37, steps = 1000\n",
      "20:39:20 [DEBUG] train episode 112: reward = 6.05, steps = 1000\n",
      "20:40:06 [DEBUG] train episode 113: reward = 12.92, steps = 1000\n",
      "20:40:53 [DEBUG] train episode 114: reward = -54.78, steps = 1000\n",
      "20:41:43 [DEBUG] train episode 115: reward = -38.07, steps = 1000\n",
      "20:42:26 [DEBUG] train episode 116: reward = -202.27, steps = 887\n",
      "20:43:15 [DEBUG] train episode 117: reward = 33.52, steps = 1000\n",
      "20:44:04 [DEBUG] train episode 118: reward = 20.29, steps = 1000\n",
      "20:44:52 [DEBUG] train episode 119: reward = 45.60, steps = 1000\n",
      "20:45:43 [DEBUG] train episode 120: reward = -18.67, steps = 1000\n",
      "20:46:33 [DEBUG] train episode 121: reward = -31.62, steps = 1000\n",
      "20:47:05 [DEBUG] train episode 122: reward = 230.61, steps = 625\n",
      "20:47:52 [DEBUG] train episode 123: reward = -23.91, steps = 1000\n",
      "20:48:44 [DEBUG] train episode 124: reward = -25.89, steps = 1000\n",
      "20:49:32 [DEBUG] train episode 125: reward = 36.88, steps = 1000\n",
      "20:50:17 [DEBUG] train episode 126: reward = 214.38, steps = 896\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "20:51:05 [DEBUG] train episode 127: reward = 2.51, steps = 1000\n",
      "20:51:55 [DEBUG] train episode 128: reward = -38.90, steps = 1000\n",
      "20:52:45 [DEBUG] train episode 129: reward = -9.13, steps = 1000\n",
      "20:53:32 [DEBUG] train episode 130: reward = 7.60, steps = 1000\n",
      "20:54:22 [DEBUG] train episode 131: reward = -22.21, steps = 1000\n",
      "20:55:10 [DEBUG] train episode 132: reward = -29.46, steps = 1000\n",
      "20:56:01 [DEBUG] train episode 133: reward = 22.89, steps = 1000\n",
      "20:56:52 [DEBUG] train episode 134: reward = -42.67, steps = 1000\n",
      "20:57:38 [DEBUG] train episode 135: reward = 167.41, steps = 931\n",
      "20:58:28 [DEBUG] train episode 136: reward = 24.68, steps = 1000\n",
      "20:59:18 [DEBUG] train episode 137: reward = -26.36, steps = 1000\n",
      "21:00:05 [DEBUG] train episode 138: reward = -32.06, steps = 1000\n",
      "21:00:54 [DEBUG] train episode 139: reward = -22.85, steps = 1000\n",
      "21:01:45 [DEBUG] train episode 140: reward = 37.13, steps = 1000\n",
      "21:02:36 [DEBUG] train episode 141: reward = -23.30, steps = 1000\n",
      "21:03:26 [DEBUG] train episode 142: reward = 4.32, steps = 1000\n",
      "21:04:16 [DEBUG] train episode 143: reward = -14.85, steps = 1000\n",
      "21:04:58 [DEBUG] train episode 144: reward = 129.96, steps = 865\n",
      "21:05:47 [DEBUG] train episode 145: reward = -25.36, steps = 1000\n",
      "21:06:37 [DEBUG] train episode 146: reward = -1.15, steps = 1000\n",
      "21:07:26 [DEBUG] train episode 147: reward = -21.08, steps = 1000\n",
      "21:08:17 [DEBUG] train episode 148: reward = -38.30, steps = 1000\n",
      "21:09:08 [DEBUG] train episode 149: reward = 2.20, steps = 1000\n",
      "21:09:58 [DEBUG] train episode 150: reward = -31.24, steps = 1000\n",
      "21:10:51 [DEBUG] train episode 151: reward = -21.62, steps = 1000\n",
      "21:11:39 [DEBUG] train episode 152: reward = -7.89, steps = 1000\n",
      "21:12:28 [DEBUG] train episode 153: reward = -31.07, steps = 1000\n",
      "21:13:17 [DEBUG] train episode 154: reward = 13.59, steps = 1000\n",
      "21:14:07 [DEBUG] train episode 155: reward = -9.35, steps = 1000\n",
      "21:14:58 [DEBUG] train episode 156: reward = -20.65, steps = 1000\n",
      "21:15:35 [DEBUG] train episode 157: reward = 206.00, steps = 732\n",
      "21:16:22 [DEBUG] train episode 158: reward = -28.85, steps = 1000\n",
      "21:17:14 [DEBUG] train episode 159: reward = 23.96, steps = 1000\n",
      "21:18:07 [DEBUG] train episode 160: reward = 43.03, steps = 1000\n",
      "21:18:59 [DEBUG] train episode 161: reward = -34.36, steps = 1000\n",
      "21:19:53 [DEBUG] train episode 162: reward = 4.18, steps = 1000\n",
      "21:20:42 [DEBUG] train episode 163: reward = -113.76, steps = 1000\n",
      "21:21:33 [DEBUG] train episode 164: reward = -9.46, steps = 1000\n",
      "21:22:25 [DEBUG] train episode 165: reward = -10.06, steps = 1000\n",
      "21:23:14 [DEBUG] train episode 166: reward = -47.17, steps = 1000\n",
      "21:24:01 [DEBUG] train episode 167: reward = 196.72, steps = 942\n",
      "21:24:51 [DEBUG] train episode 168: reward = 32.09, steps = 1000\n",
      "21:25:41 [DEBUG] train episode 169: reward = 39.45, steps = 1000\n",
      "21:26:25 [DEBUG] train episode 170: reward = 221.70, steps = 879\n",
      "21:27:16 [DEBUG] train episode 171: reward = 24.89, steps = 1000\n",
      "21:28:10 [DEBUG] train episode 172: reward = -33.51, steps = 1000\n",
      "21:28:56 [DEBUG] train episode 173: reward = 142.32, steps = 898\n",
      "21:29:48 [DEBUG] train episode 174: reward = 15.96, steps = 1000\n",
      "21:30:38 [DEBUG] train episode 175: reward = -10.61, steps = 1000\n",
      "21:31:31 [DEBUG] train episode 176: reward = 35.98, steps = 1000\n",
      "21:32:21 [DEBUG] train episode 177: reward = 1.48, steps = 1000\n",
      "21:33:10 [DEBUG] train episode 178: reward = 46.10, steps = 1000\n",
      "21:34:00 [DEBUG] train episode 179: reward = 16.56, steps = 1000\n",
      "21:34:50 [DEBUG] train episode 180: reward = 187.75, steps = 976\n",
      "21:35:39 [DEBUG] train episode 181: reward = -57.60, steps = 1000\n",
      "21:36:28 [DEBUG] train episode 182: reward = -21.21, steps = 1000\n",
      "21:37:21 [DEBUG] train episode 183: reward = -25.96, steps = 1000\n",
      "21:38:10 [DEBUG] train episode 184: reward = -12.24, steps = 1000\n",
      "21:39:02 [DEBUG] train episode 185: reward = -4.27, steps = 1000\n",
      "21:39:54 [DEBUG] train episode 186: reward = -7.93, steps = 1000\n",
      "21:40:44 [DEBUG] train episode 187: reward = -8.10, steps = 1000\n",
      "21:41:37 [DEBUG] train episode 188: reward = -9.60, steps = 1000\n",
      "21:42:28 [DEBUG] train episode 189: reward = 143.85, steps = 966\n",
      "21:43:04 [DEBUG] train episode 190: reward = 249.52, steps = 724\n",
      "21:43:34 [DEBUG] train episode 191: reward = 185.99, steps = 618\n",
      "21:44:25 [DEBUG] train episode 192: reward = -28.12, steps = 1000\n",
      "21:45:14 [DEBUG] train episode 193: reward = -54.83, steps = 1000\n",
      "21:46:05 [DEBUG] train episode 194: reward = 71.56, steps = 1000\n",
      "21:46:56 [DEBUG] train episode 195: reward = 58.54, steps = 1000\n",
      "21:47:39 [DEBUG] train episode 196: reward = 146.99, steps = 795\n",
      "21:48:31 [DEBUG] train episode 197: reward = 65.29, steps = 1000\n",
      "21:48:55 [DEBUG] train episode 198: reward = 219.04, steps = 467\n",
      "21:49:15 [DEBUG] train episode 199: reward = 267.43, steps = 427\n",
      "21:49:37 [DEBUG] train episode 200: reward = 229.70, steps = 446\n",
      "21:50:29 [DEBUG] train episode 201: reward = -49.57, steps = 1000\n",
      "21:51:20 [DEBUG] train episode 202: reward = -104.82, steps = 1000\n",
      "21:51:37 [DEBUG] train episode 203: reward = 254.65, steps = 354\n",
      "21:52:14 [DEBUG] train episode 204: reward = 210.89, steps = 742\n",
      "21:53:04 [DEBUG] train episode 205: reward = -57.09, steps = 1000\n",
      "21:53:55 [DEBUG] train episode 206: reward = 112.75, steps = 1000\n",
      "21:54:10 [DEBUG] train episode 207: reward = 247.54, steps = 322\n",
      "21:54:58 [DEBUG] train episode 208: reward = 140.42, steps = 1000\n",
      "21:55:31 [DEBUG] train episode 209: reward = 271.82, steps = 682\n",
      "21:55:59 [DEBUG] train episode 210: reward = 248.92, steps = 570\n",
      "21:56:48 [DEBUG] train episode 211: reward = 135.83, steps = 1000\n",
      "21:56:58 [DEBUG] train episode 212: reward = 253.09, steps = 219\n",
      "21:57:11 [DEBUG] train episode 213: reward = 279.45, steps = 254\n",
      "21:57:59 [DEBUG] train episode 214: reward = 136.24, steps = 1000\n",
      "21:58:22 [DEBUG] train episode 215: reward = 264.55, steps = 478\n",
      "21:59:12 [DEBUG] train episode 216: reward = -57.74, steps = 1000\n",
      "22:00:00 [DEBUG] train episode 217: reward = 179.46, steps = 1000\n",
      "22:00:48 [DEBUG] train episode 218: reward = -47.86, steps = 1000\n",
      "22:01:38 [DEBUG] train episode 219: reward = -36.88, steps = 1000\n",
      "22:02:27 [DEBUG] train episode 220: reward = -20.46, steps = 1000\n",
      "22:03:08 [DEBUG] train episode 221: reward = -58.69, steps = 1000\n",
      "22:03:16 [DEBUG] train episode 222: reward = -81.68, steps = 213\n",
      "22:03:21 [DEBUG] train episode 223: reward = 13.49, steps = 161\n",
      "22:03:36 [DEBUG] train episode 224: reward = 240.15, steps = 422\n",
      "22:03:57 [DEBUG] train episode 225: reward = -123.34, steps = 608\n",
      "22:04:04 [DEBUG] train episode 226: reward = 29.01, steps = 192\n",
      "22:04:09 [DEBUG] train episode 227: reward = 51.34, steps = 153\n",
      "22:04:46 [DEBUG] train episode 228: reward = -56.91, steps = 1000\n",
      "22:04:53 [DEBUG] train episode 229: reward = 11.96, steps = 183\n",
      "22:05:07 [DEBUG] train episode 230: reward = 252.65, steps = 423\n",
      "22:05:20 [DEBUG] train episode 231: reward = 240.54, steps = 368\n",
      "22:05:47 [DEBUG] train episode 232: reward = 284.90, steps = 757\n",
      "22:06:01 [DEBUG] train episode 233: reward = 270.86, steps = 399\n",
      "22:06:16 [DEBUG] train episode 234: reward = -247.49, steps = 421\n",
      "22:06:53 [DEBUG] train episode 235: reward = -48.60, steps = 1000\n",
      "22:06:59 [DEBUG] train episode 236: reward = 48.83, steps = 157\n",
      "22:07:34 [DEBUG] train episode 237: reward = 120.69, steps = 1000\n",
      "22:07:51 [DEBUG] train episode 238: reward = 262.11, steps = 457\n",
      "22:07:57 [DEBUG] train episode 239: reward = 38.00, steps = 143\n",
      "22:08:36 [DEBUG] train episode 240: reward = 13.72, steps = 1000\n",
      "22:08:40 [DEBUG] train episode 241: reward = 39.62, steps = 139\n",
      "22:09:00 [DEBUG] train episode 242: reward = 244.20, steps = 510\n",
      "22:09:31 [DEBUG] train episode 243: reward = 129.45, steps = 763\n",
      "22:10:08 [DEBUG] train episode 244: reward = -42.89, steps = 1000\n",
      "22:10:39 [DEBUG] train episode 245: reward = 273.97, steps = 889\n",
      "22:10:52 [DEBUG] train episode 246: reward = 235.31, steps = 369\n",
      "22:11:00 [DEBUG] train episode 247: reward = 275.66, steps = 241\n",
      "22:11:10 [DEBUG] train episode 248: reward = 273.43, steps = 282\n",
      "22:11:18 [DEBUG] train episode 249: reward = 232.74, steps = 244\n",
      "22:11:38 [DEBUG] train episode 250: reward = 244.36, steps = 551\n",
      "22:12:03 [DEBUG] train episode 251: reward = 234.59, steps = 742\n",
      "22:12:17 [DEBUG] train episode 252: reward = 275.36, steps = 385\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "22:12:28 [DEBUG] train episode 253: reward = 279.71, steps = 329\n",
      "22:13:04 [DEBUG] train episode 254: reward = 184.40, steps = 1000\n",
      "22:13:04 [INFO] ==== test ====\n",
      "22:13:04 [DEBUG] test episode 0: reward = 285.31, steps = 234\n",
      "22:13:04 [DEBUG] test episode 1: reward = 304.13, steps = 206\n",
      "22:13:04 [DEBUG] test episode 2: reward = 281.95, steps = 195\n",
      "22:13:05 [DEBUG] test episode 3: reward = 267.08, steps = 225\n",
      "22:13:05 [DEBUG] test episode 4: reward = 48.10, steps = 147\n",
      "22:13:05 [DEBUG] test episode 5: reward = 282.05, steps = 273\n",
      "22:13:05 [DEBUG] test episode 6: reward = 258.97, steps = 230\n",
      "22:13:06 [DEBUG] test episode 7: reward = 279.16, steps = 191\n",
      "22:13:06 [DEBUG] test episode 8: reward = 283.77, steps = 279\n",
      "22:13:06 [DEBUG] test episode 9: reward = 253.03, steps = 215\n",
      "22:13:07 [DEBUG] test episode 10: reward = 276.79, steps = 352\n",
      "22:13:07 [DEBUG] test episode 11: reward = 288.32, steps = 229\n",
      "22:13:07 [DEBUG] test episode 12: reward = 285.80, steps = 252\n",
      "22:13:08 [DEBUG] test episode 13: reward = 266.10, steps = 245\n",
      "22:13:08 [DEBUG] test episode 14: reward = 289.92, steps = 212\n",
      "22:13:08 [DEBUG] test episode 15: reward = 285.90, steps = 212\n",
      "22:13:08 [DEBUG] test episode 16: reward = 277.29, steps = 182\n",
      "22:13:08 [DEBUG] test episode 17: reward = 271.98, steps = 205\n",
      "22:13:09 [DEBUG] test episode 18: reward = 281.33, steps = 279\n",
      "22:13:09 [DEBUG] test episode 19: reward = 265.12, steps = 197\n",
      "22:13:09 [DEBUG] test episode 20: reward = 266.67, steps = 294\n",
      "22:13:10 [DEBUG] test episode 21: reward = 277.62, steps = 215\n",
      "22:13:10 [DEBUG] test episode 22: reward = 248.86, steps = 390\n",
      "22:13:10 [DEBUG] test episode 23: reward = 258.59, steps = 207\n",
      "22:13:11 [DEBUG] test episode 24: reward = 276.09, steps = 201\n",
      "22:13:11 [DEBUG] test episode 25: reward = 278.85, steps = 227\n",
      "22:13:11 [DEBUG] test episode 26: reward = 282.50, steps = 294\n",
      "22:13:11 [DEBUG] test episode 27: reward = 260.52, steps = 220\n",
      "22:13:12 [DEBUG] test episode 28: reward = 240.41, steps = 186\n",
      "22:13:12 [DEBUG] test episode 29: reward = 291.17, steps = 197\n",
      "22:13:12 [DEBUG] test episode 30: reward = 277.23, steps = 305\n",
      "22:13:14 [DEBUG] test episode 31: reward = 151.01, steps = 1000\n",
      "22:13:14 [DEBUG] test episode 32: reward = 284.86, steps = 191\n",
      "22:13:15 [DEBUG] test episode 33: reward = 250.68, steps = 196\n",
      "22:13:15 [DEBUG] test episode 34: reward = 270.75, steps = 216\n",
      "22:13:15 [DEBUG] test episode 35: reward = 272.77, steps = 196\n",
      "22:13:15 [DEBUG] test episode 36: reward = 277.00, steps = 239\n",
      "22:13:15 [DEBUG] test episode 37: reward = 271.24, steps = 185\n",
      "22:13:17 [DEBUG] test episode 38: reward = 178.84, steps = 1000\n",
      "22:13:17 [DEBUG] test episode 39: reward = 263.73, steps = 241\n",
      "22:13:18 [DEBUG] test episode 40: reward = 274.45, steps = 221\n",
      "22:13:18 [DEBUG] test episode 41: reward = 267.51, steps = 205\n",
      "22:13:18 [DEBUG] test episode 42: reward = 261.28, steps = 210\n",
      "22:13:18 [DEBUG] test episode 43: reward = 61.54, steps = 146\n",
      "22:13:18 [DEBUG] test episode 44: reward = 269.73, steps = 214\n",
      "22:13:18 [DEBUG] test episode 45: reward = 270.03, steps = 178\n",
      "22:13:19 [DEBUG] test episode 46: reward = 259.18, steps = 195\n",
      "22:13:19 [DEBUG] test episode 47: reward = 264.74, steps = 229\n",
      "22:13:19 [DEBUG] test episode 48: reward = 310.17, steps = 242\n",
      "22:13:19 [DEBUG] test episode 49: reward = 273.44, steps = 220\n",
      "22:13:20 [DEBUG] test episode 50: reward = 275.92, steps = 210\n",
      "22:13:20 [DEBUG] test episode 51: reward = 273.63, steps = 252\n",
      "22:13:22 [DEBUG] test episode 52: reward = 156.95, steps = 1000\n",
      "22:13:22 [DEBUG] test episode 53: reward = 267.19, steps = 190\n",
      "22:13:22 [DEBUG] test episode 54: reward = 281.98, steps = 331\n",
      "22:13:22 [DEBUG] test episode 55: reward = 267.73, steps = 198\n",
      "22:13:23 [DEBUG] test episode 56: reward = 284.35, steps = 183\n",
      "22:13:23 [DEBUG] test episode 57: reward = 276.08, steps = 214\n",
      "22:13:23 [DEBUG] test episode 58: reward = 269.91, steps = 210\n",
      "22:13:23 [DEBUG] test episode 59: reward = 281.09, steps = 189\n",
      "22:13:25 [DEBUG] test episode 60: reward = 160.82, steps = 1000\n",
      "22:13:25 [DEBUG] test episode 61: reward = 266.61, steps = 199\n",
      "22:13:26 [DEBUG] test episode 62: reward = 278.77, steps = 256\n",
      "22:13:26 [DEBUG] test episode 63: reward = 267.05, steps = 207\n",
      "22:13:26 [DEBUG] test episode 64: reward = 290.68, steps = 194\n",
      "22:13:26 [DEBUG] test episode 65: reward = 254.63, steps = 186\n",
      "22:13:27 [DEBUG] test episode 66: reward = 275.16, steps = 246\n",
      "22:13:27 [DEBUG] test episode 67: reward = 289.21, steps = 202\n",
      "22:13:27 [DEBUG] test episode 68: reward = 291.09, steps = 230\n",
      "22:13:27 [DEBUG] test episode 69: reward = 285.46, steps = 215\n",
      "22:13:28 [DEBUG] test episode 70: reward = 268.26, steps = 230\n",
      "22:13:28 [DEBUG] test episode 71: reward = 280.02, steps = 177\n",
      "22:13:28 [DEBUG] test episode 72: reward = 279.33, steps = 195\n",
      "22:13:30 [DEBUG] test episode 73: reward = 165.28, steps = 1000\n",
      "22:13:31 [DEBUG] test episode 74: reward = 159.33, steps = 1000\n",
      "22:13:32 [DEBUG] test episode 75: reward = 281.31, steps = 301\n",
      "22:13:32 [DEBUG] test episode 76: reward = 266.59, steps = 206\n",
      "22:13:32 [DEBUG] test episode 77: reward = 284.99, steps = 192\n",
      "22:13:32 [DEBUG] test episode 78: reward = 280.58, steps = 202\n",
      "22:13:33 [DEBUG] test episode 79: reward = 244.67, steps = 170\n",
      "22:13:33 [DEBUG] test episode 80: reward = 274.72, steps = 217\n",
      "22:13:33 [DEBUG] test episode 81: reward = 258.48, steps = 182\n",
      "22:13:33 [DEBUG] test episode 82: reward = 274.71, steps = 242\n",
      "22:13:34 [DEBUG] test episode 83: reward = 238.50, steps = 527\n",
      "22:13:35 [DEBUG] test episode 84: reward = 274.80, steps = 271\n",
      "22:13:35 [DEBUG] test episode 85: reward = 243.63, steps = 202\n",
      "22:13:35 [DEBUG] test episode 86: reward = 255.29, steps = 210\n",
      "22:13:35 [DEBUG] test episode 87: reward = 257.04, steps = 189\n",
      "22:13:36 [DEBUG] test episode 88: reward = 272.00, steps = 318\n",
      "22:13:36 [DEBUG] test episode 89: reward = 257.17, steps = 180\n",
      "22:13:36 [DEBUG] test episode 90: reward = 276.28, steps = 177\n",
      "22:13:36 [DEBUG] test episode 91: reward = 275.20, steps = 206\n",
      "22:13:37 [DEBUG] test episode 92: reward = 248.30, steps = 169\n",
      "22:13:37 [DEBUG] test episode 93: reward = 248.01, steps = 414\n",
      "22:13:37 [DEBUG] test episode 94: reward = 62.84, steps = 137\n",
      "22:13:38 [DEBUG] test episode 95: reward = 267.50, steps = 216\n",
      "22:13:38 [DEBUG] test episode 96: reward = 278.84, steps = 205\n",
      "22:13:38 [DEBUG] test episode 97: reward = 58.19, steps = 145\n",
      "22:13:38 [DEBUG] test episode 98: reward = 284.43, steps = 204\n",
      "22:13:38 [DEBUG] test episode 99: reward = 25.31, steps = 135\n",
      "22:13:38 [INFO] average episode reward = 254.60 ± 55.07\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX8AAAD4CAYAAAAEhuazAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAABjEklEQVR4nO29eZhcV3nn/33vUktXb5K6tcuWbMuLpOBNFo5ZTOKVJdgJYXDIBCcQPMM4Q/glJMGBZyCZ8W/IQEICxBDzG8AkgOPEARuI7RhjsI1tbHmXbMuSLNnau6Xeu2u5y/n9cc8599xbt6pu9aLq6j6f5+mnq2/dqjq3qus97/m+yyHGGDQajUazuDBaPQCNRqPRnHy08ddoNJpFiDb+Go1GswjRxl+j0WgWIdr4azQazSLEavUA0tLX18fWr1/f6mFoNBpNW/HUU08dZ4z1x4+3jfFfv349tm/f3uphaDQaTVtBRK8lHdeyj0aj0SxCZmz8iShHRE8Q0XNEtJOI/oIfX0pE9xPRbv57ifKYm4hoDxHtIqKrZjoGjUaj0TTHbHj+ZQC/yhg7F8B5AK4moosBfALAA4yxjQAe4H+DiDYBuA7AZgBXA7iFiMxZGIdGo9FoUjJj488CJvifNv9hAK4BcBs/fhuAa/ntawDczhgrM8b2AdgDYNtMx6HRaDSa9MyK5k9EJhE9C2AAwP2MsV8AWMEYOwIA/PdyfvoaAAeUhx/kx5Ke9wYi2k5E2wcHB2djqBqNRqPBLBl/xpjHGDsPwFoA24hoS53TKekpajzvrYyxrYyxrf39VZlKGo1Go5kms5rtwxgbAfBTBFr+MSJaBQD89wA/7SCAdcrD1gI4PJvj0Gg0Gk19ZiPbp5+IevntPIDLAbwM4G4A1/PTrgdwF799N4DriChLRBsAbATwxEzHodFoNCeLx/aewIuHx1o9jBkxG0VeqwDcxjN2DAB3MMZ+SESPAbiDiD4E4HUA7wUAxthOIroDwIsAXAA3Msa8WRiHRqPRnBRu+rfn0dORwV03vmnOXsP3GVyfIWPNTTnWjI0/Y+x5AOcnHD8B4LIaj7kZwM0zfW2NRqOpxSfufB4/fmkA2z91+aw+L2MMR0ZL2H9iCkdHS1jZk5vV5weA0aKDK/7mZzitv4Dbb/jlWX9+QFf4ajSaBcrtTx7A8YnyrD/vWMlF2fUBAP/x4tGmH19xfXz9kX1wPB83fGs7rvnyI9i+fyhyzke/+wwGxst4/NWhGs8yc7Tx12g0bc9DrwzijD//dwxNVub8tQbGSvL2fTubN/7/8tQB/OUPX8StD72KR/eewHMHR/Gndz4fOeep14YBAEsLmZkNtg7a+Gs0mnnHq4MT+O/ffQZlN1048B8ffw2uz/Dw7qAe6ITi8c/2PuUD48Fzr+7J4bUTU00/3jYCs/vcgRFMlF0YBBwcLspxjpcceXyy7M7ewGNo46/RaOYdP3tlED947jB2H5tofDKAM5Z3AgD2Dk4CAF5RHndktIRL/vcD2DMwPitjO8Y9/1W9eSTNK4PjZbw6WHvcwpt/7uAIAOD8U5ag4voYnnIAAEdHg+c/rb8TZdeH6/mzMu442vhrNJp5xyD3rg+NFFOdn7eD9mB7BwKju1sx9K8cG8fh0RL2HW/eS0/i2FgwtpXdOfgJ1v/z9+3Cf/v20zUfLx4hnuf8db0AgCOjwbUe5ZPL6f0FAMCUMzfJkNr4azSaeYcI1B5WjP/IVAV7BpI9aiEPvXQ0yL1/5Vho/MdKgXTi+bPjQQ+Ml9CZtdCVsxKN/0ixgrGiU/Pxnh99zPmnBA2Phcd/ZFQY/2A1M1WeG+PfNpu5aDSaxcPxiSBwqxr/3/zqY9gzMIH9n31n1fklJzDs+45PYrLsRuSiUW6IXX9m2v/olIOP/+tzOD5RxvKuLIgISU9Zdn04dV5LNf5EwBvW9gAIjb6YBDb0BZ7/ZGVudH/t+Ws0mpPCaNHBVV94KFVlrJB9Do+EmTXC6y8pMsgrx8ax7/ik9PwZA146MoaRqdDzFl543ONulqdfH8b9Lx7DM6+PYHl3FgYFhVhxyk59nd5TVgt9nVms7s3DNCji+fd1ZrCkI4gNzJXnr42/RqM5KRwYmsKuY+N4ngc66yFkH1XzN3hLyIGxMJPnpn97ATf/6EXp+QNBNk7R8WRl7OgsGf+sUmm7vCsHgyhR9im7HlwvevzRPcex6+g4H0c41lU9OZgGYUVXFnsHJ3DLT/dg3/EJrOzJoSMTxDG056/RaNqaIvfYR+ro4UCQmpmk+fd1ZgEAx8bD1cB4ycFo0UHJ8WDy2aFY8VB0PPTmbQCBXAOkM/6TZReP7D6eeJ8q5azozsI06sk+Uc//U3ftwJcf3MPHER5f2R1UB6/oyeGeHUfxf+7dhcdfHcLK7jw6soEqP6WNv0ajaWeKFW78p+ob/9GiA8dj6MnbGBgvS0lHGn+lyKrs+ig6HsqujyUdgbEvOh5KjocebvzHSumN/13PHsbvfP0XcsJQUaWci9YvBRFqeP5+ledfdnxMlasDz6t4a4hVsRYRK3uyKAjPX8s+Go2mnZnixn+0WL8KV+j95/IUSKGF93UJ4x/KPiXHw1QlauxL3Pj38slAyj4pir2mKi4YQ2JxmQgY/+ijb8aVm1fCIErM8y+7HlyfRYrLHM+XKx818LxuaQcAYGV3HgBw5aYVAIBVPaHnLybN2UYbf40mBXc+dRCfveflVg+jrSk6gefbyPMf5JLPuTwLRuj+XbnAGA7EPf+Kh7LjywDpeMnlK4fg72Y0f4d77EkThfDmLV6ha1Dyc5Z5/EE18qrxF0HiW3/nQrz/jacACDJ++jqz+Nxvnou/ePdm/MYFa0LPX8s+Gk3r+Okrg/jRC3rPoZkwlVL2EZ7/WSu7AADDk8H5wmiqsk/J8bjs46GQtWAZhJGpYGUhVgLNGH8h7SSd63K5xjKD2ELtgC83/p5q/Jn04MWkcNH6pejIBBPateevwRN/fhl6Omxcf8n6wPPPCM1fe/4aTctwvWoddyHy4xePzZnMUJSyT33jL3L8hQ4uvHBPGv9gcmCMoez6XPbxkbMN5DMmhvjkUiX7pPH8+TlJ9WBiVSB68xhGbdkneC5feawvU1TFOEwzuqOtYUT/zlgGbJPmrL+PNv4aTQpcvrHGQubwSBG//63tuHfnkTl5/rTGf3C8DNskLC0EGr8IkErjz7N9HI+BsaBF8pTjImebyNsmhnlnT5HtMy4rfJvw/BOsuhiHKT3/6oCvmJCC50qWfaTxp6TtzKN0ZCzt+Ws0rcTzWVXhzlOvDddt4NVuCCMzV8ZG9KgRskwtxksOunM2LO4JuzEdXuT5l5Sg7Mikg6wVeP7D/PmF5y9IM3mLc5ImitDzry37iAkpGHc4afkMVbKPaTQ2/oWMqT1/jaaVOJ5fZTz+7M7n8aWf7GnRiGYfx6v2WGcTYfwmKx4qbu0K2IrrI2sZUlv3YgZ5ouxiouzKwCoAjJerPf/ufNT4J1XjxhHvQZKWL4y5ZQZmM6m9g5olJCQk8ZyiEE2Mw0ph/Duy89jzJ6J1RPQgEb1ERDuJ6A/58aVEdD8R7ea/lyiPuYmI9hDRLiK6aqZj0GjmmsDzj37Tp8runOnj02Wq4mK8VF9WqYUwyM4ctRBW36t60k/Z9ZGxDOkZi0lXNcgjU5VImwcAyNkmcraJIen5RzdCSeX58884aQIUj7cU2QeITiplZVITk4V4XMUL2j404/l3ZMx5ne3jAvhjxtg5AC4GcCMRbQLwCQAPMMY2AniA/w1+33UANgO4GsAtfPN3jWbe4vqsSgqoeGzODOV0+dT3d+DG7zwzrceKa6nM0TWprYnr5foHnr8pUyrjnr+4XY6tHrKWgbxtSg+7M2tBta9J3nwckdGT6PnHPHah2avnqmMS76ejHCu5PnzGYFCwcmhER8acv719GGNHGGNP89vjAF4CsAbANQBu46fdBuBafvsaALczxsqMsX0A9gDYNtNxaDRzietVl+w7Xv3uja1gcLwcyYNvhoo0VnMl+4QebL10z4oX9fylFKO8/Y7HEj3/fMZU/jaQtcK/03j+Ms8/KdVTyD5Ktg+AiPRTVsYknkv9vylWggKwNF4/ABQy1rz2/CVEtB7A+QB+AWAFY+wIEEwQAJbz09YAOKA87CA/lvR8NxDRdiLaPjg4OJtD1WiawvODQJ66xK+4fsSrmw8kxSbqce+OI/jeMwf5Y6Ma9WwzVfFkc7R6xr/sBk3ZhIctDLGrGNF6nr8gb5vI2qGJS6P518v2kQFfLvsIx72W5+/K9zO8v+R48Jsw/vNa8xcQUSeAOwF8jDFWr2dr0lUnfiqMsVsZY1sZY1v7+/tnY5gazbQQBjWeu+3O0gYhs4XrVctT9finx1/HN36+H4Ci+c/RNU1VPJm7X6+5mwj4xjV/VYZ3fT/iZQNAlmv+gnzGjHTiTOX5yzz/pFTPwGgLucbgv9V5IiL7+CKArsg+TuD5i9VDI+Z9tg8R2QgM/7cZY//GDx8jolX8/lUABvjxgwDWKQ9fC0CXTmrmNW5MDvB53r8zzwq/HL+5OITj+VWB3mZknz0DE6k8aiAwfCu58U8T8I17/n4DzT9nGchnQpOWt82I7DPTCl/H9yMeu7iprhLUCclNWEkVHQ+ez5DS8Z/fef4UTIP/F8BLjLG/Ue66G8D1/Pb1AO5Sjl9HRFki2gBgI4AnZjoOjWYuER6+MPZSH59nAd9mK5E9n1Ub/5TXdGyshCu/8DM88PJA45MReP5BH/z6uf4V10fGTPD8fSYlF9dnVc3XRKqn+rfq+acz/vV7+9gR418/4CsmkooymRYrgfEX6aKNKGSDbB+WIljdLLOxjeObAPwOgBeI6Fl+7M8BfBbAHUT0IQCvA3gvADDGdhLRHQBeRJApdCNjbH7ly2k0MeIZJ8L4z7eWD67HmpKiHMWDbjbVc2TKgc8gi6oaMVUJ+u/kbLNuimzF9ZG1TRARLINkZa3PGDKmAccLNktRN3ABqjX/rGVENP9mZJ9aAV/VaEvZRxmGGoQWz6V+HkUu+xgpMn2AwPNnLKgRUIPZs8GMjT9j7BEk6/gAcFmNx9wM4OaZvrZGc7IQHr9cAcyxPj5dHN9vSopyPV9ZxVQHKOshJou0MYZixUVHxoRlUF1DXOaePxDkwquef9Y2MVnxAs0/yfPnzdDyfPJQZR/fZ/jod5/Byp4c/vwd5yS+dv3GbixSmGU0DPhWT6Yi4JumwAsA3v/GU/AbF6yJrGBmC72Bu0aTAplxEjOQ80/2qW5DUQ9V9qmIhmQpHx+ufhqfzxhD0fGQt01kLKNuLUHZ9aXHbhkET5FihBH0/GrPP5B9DH47+B0P+O46Oi43d0lCfL7JFb5MFngBaqpnrTz/6slUeP5ps3168rbsTjrb6PYOGk0K4j1fhMGcf7JPc6me0YBvcxNa/HH1KLs+fBZk4FiGUXfCKLteTc9f7Murav5CQRG9fQBI+Uc1/j5jcPz6MRFHNpFLvk/N0hFZP5GAr7IaCeNEap5/UOSV1vjPJdr4azQpiH+R41JJPXyf4eP/8hx2Hh6duwFynCa7j7o+k9fSbBDbqSORxBEaf0fGhGVSXQMsUj2BoI+OGm8Rk4Kq+XfnAs84p6R65jLC+EeLvLwG2VDxrK74fbZZLftEUj0dP3K++hsIPf+0ss9coo2/RpMCz0v2/NMYypGig3996iB+vid5Y/DZxPV8XpCWbgIQdQGqUaw0qfmniXuI1g4dGRMZs7bsw1gwGQnjr3r+vs+kHORxzd8yCJ18u8OcHQZ8pecfK/IKAuJ1PP86jd28mFyTtr1DJab5e75f1bu/FWjjr9GkQBZ5xaSRNHq3OKfspPOoZ0JSVWnd85UVTShlNav5p/f8c3Z9z1+0RBbyjprt4zHF8/cZyk4wSXQoXr6QfXIJso/r+0FhXj3Pv25LZx92QrZPpL1DRPZJ8PxFqqc2/hpNe+DGNhSROfEpJA9hJONFSXOBrCpNmYUkDFPZ9ZvO85cTYFOyjxVo/jXGJ96rTILn7/nhcc9nKLkecrYpjX+i5x8p8kLDwryG2T6K7CPbOzTo6plc5KWNv0bTFsTbOzQj+4QGdu7LWZr3/EMZKyxgS/fYchMrhSnenKwjY8K2jJqvISpkhdG2DIpk4Ijjjhd6/lLnVzX/BM/fE55/nYmxbmO3WFuGxCIvZXWXFEAvOaLISxt/jWbe4/vh7kzxIi/GGgc8nZPk+TPG6soWSbiKLh129Wwu2yfNawnNP58xYRuUOGEcGJqSbR9Uzz9Ms/WVVE8fJdePeP4Z01BkH57qqWj+HhOpsHU8f0ViqrrP86N5/vyp47KPeO1wJRWcYJvUdJHXXKLz/DWaBsSbuQGI7ETleD5Mo3b1pfjyz7Xmr8ovaXV7R/H8m63wjRu3epS47JOvo/n/2pcfweXnrAAQeuyqROQrsYBA8w+6f+YzQe2AYVBN2SdrGfD8IBheL0AtVxk1sn0ief41Ar6dWQslp6LEicKspJLjwWda89do2oL4JiJA1OA1MpbCeM217BPZMDyl5+9FZJ+ohv8v2w/gmi8/UvOxMkCcIr4gNi/P2yZs06gywGXXw8iUg9eHpgAke/5qnn+g+QdtIPK2hRw/Lo1/Jir7FLKWNPx18/zrtXT2kwO+LGb8Czz7KB5D6c7bQT9/b37k+WvPX6NpQMSjjnlzQONsl5Ml+6gGNW3VbZLxF0Z919FxPHdwFIyxxF2nQuOfrsgLCGQY2zSqJsxJvlvVEN9/V2T12KYS8FUqfAPN30POMnD+Kb1SLooXeYnJoiNjykyiugHfFC2dBYnZPryK2aDq+EtXzpIB38wctGtoFm38NZoGqMZd3I7LPvWQss8cG/+I559CilHPqXie7D4Z91jLXFuvfnz6gK94vzKmEQniCkTP+hMTZQBBb34g6vn7fhjwFZp/T97Gf774VPzni08NHmcZWNJhY0V30Dp6/bICurIW+ruysulavZVKvSIvx4sHfIPfcdkn2HzeqOrn35WzMFH2YFC6/XvnmtZPPxrNPCe6g1R14U4jiSU0oo1ln7GSg8/cvbNqi8JU41RXIymkGNXAJaV6yhTVGrGKchN5/uLas0L2iXv+PBtIbPIiPP+gFUTo+cc1/1zMgyYi/PiPLpWTwdvO6sezn74SPXlbyU5q3N4haTXjen6kwle2d4i8jx6ylghqRyfTQsZCief5a+Ov0bQB6pfbSfD8G3m+bhMB3+37h/DNR/fjhUPNt4JQJ6E0BlmVidSAb7i6CX6Xakxazcg+qudvm1S1MhGev3CiRZaO8PxFxpXM9vGYbP0cZ1lnVk4SRATTIJhEcgKqtVITW3UCtTdwV1s6CwMe38kraxuwrbB/kcPbUuQzJkquLvLSaNoG1ZDGi7zit5NopshLTBCVaUhEUc+/sUFWryui+cd+11qFhAHidLIPUaDhW2Z1Y7eJcvQ1pOdvElzflwFYcdzxgw3c07Y6Ng2SvYBqvTfq55j0kbq+37ils+MjawXN68Rk7LjBiiFjGqi4vi7y0mjaBTfi+SeletY3tElxglrEN1ZpBicSm0hRfOZHryEu+4h8/3jrZEGzXT0zpgEiCjx/P9nzF2Rj2T5i0jUM4sd8HotIZ8Isk2QBWa3eR+rnXLOlc4OAb8n1eFA7rGUQKwbbMniRmS7y0mjaAjfiETaf7dNMqqc4ZzrB4bgxb3h+POArK2l5n/+Gnn/6gjKxLy+AGtk+ceOvVPj6TBpj0yB5LPD80+1uZRCh1GDCTvqcVRwvKvtQguc/XnLRnbMitQwV3hMoYxpBa2ufwUy5gftc0voRaDTznIjnLyt8VcPZQPZxm5B93PQTRdU4Vc8/hRQTl30qyms6XigD1TL+zRSFBVkwwqAbNbN9BPE8f2GMTbG1o8dkZk0aLIOicZqE98dJkPdUPN+PtXTmnr9y7ljRQXfOhp0k+yie/zxw/GfH+BPR14logIh2KMeWEtH9RLSb/16i3HcTEe0hol1EdNVsjEGjmSsiRV4Jsk/DgK+fPtVzJpp/M6uRYFzRgG+8cE2Mt1RjLOL+NJ6/2qM/CPjGs31imn+kwpdBDFXIPhVuRNPmy8dbKCd6/sr7UUv2ibR0NqKyT9n1UHZ9dEnPP5R9hOcvNP+F5Pl/E8DVsWOfAPAAY2wjgAf43yCiTQCuA7CZP+YWIprdnYk1mlnESQikJh1r9PhyivTNeLC1GZJiE2nPV1M9g8ezhp5/mOefwvh7qvGvln0m6mj+rhcGfC0jCBhP8ckirfGPZ9ckTdhJgX2VeIVvXPYZLwXX0J23g4CvIvtY3PP3WfC32XrbPzvGnzH2EICh2OFrANzGb98G4Frl+O2MsTJjbB+APQC2zcY4NJq5QDUEahdMQSND3UyRl5ggptMHyGmgWdc7v8JlHmEj1f7+DWWfFBKT6MMDBMFXn0Xlklqyj9D3hVducM1ftIjOpLSi8bz6pAm70ftXO+AbnDvGaxS6czavTA6LvIIU12CspYq3oDz/JFYwxo4AAP+9nB9fA+CAct5BfqwKIrqBiLYT0fbBwcE5HKpGUxvVUEwn4Kv2zGkkEclsn+l4/k329lENnMjz78hY8u9wxVIj26dO7/ukc9WAbzDG8HlVz9+g0FMP8/yD+4TmL3oFpfX848Y/aWWU9DkLRMfUJOMvFKIx6flbPJ01bO9gm4Yc65TjLdo8/6SrTvzvYYzdyhjbyhjb2t/fP8fD0miScWNaOBA1zo2LvNKvEmaS6uk22dvHiQd8PV+2R1Y3PalV5NVMV0/Rex+ADJqqj5tS8vwzliGrZy3e28eT2T6AaZLcHyC1509x2aeB5x/T/MVkoGb7CPst7lM9f8sgqKmzlknImGFF8EKv8D1GRKsAgP8e4McPAlinnLcWwOE5HIdGMyOi7R1C2UcYsbSyD9BYzhFZPjPP80+T6lkd8O1UOlKmlX1S9fZRPH/RH0d93GTFRU8+2Ig9E6uiFRW+QOBtW0bzmn9cZknK9lHfs3hjN1caf7Wff0z2KXHjn7cjcQ2x/aM61oVu/O8GcD2/fT2Au5Tj1xFRlog2ANgI4Ik5HIdGMyOS2js4XiiRpJV9gMa6v5gcZprqmUaHV69LtB3oyAaev1gJAI2LvNJn+wTPneT5T5RdrOTN2NSWDUFaqB+menLNv3njH/27UbZP3PMXn6GdsJOXOFUEfGW2j9yEhslUz3A8C8T4E9F3ATwG4CwiOkhEHwLwWQBXENFuAFfwv8EY2wngDgAvArgXwI2Msbnf306jmSbR/O9Q9ilkxJaC6VI9gcZGffZknxQB30jAle+xazfh+cveNWny/D2lZUN0p6vg9V0s784CiHr+lsjzV4q8TCXga6cO+MY8/0TZR/2co/epk48g3t4hKvsYEUfBVgK+8edpFbPS0pkx9ls17rqsxvk3A7h5Nl5bo5lrEj1/l6FDSCQNPF/VkDf0/GcQ8G1mgxkgKruIgKvw/NVUz2JD2Sed5x8P+KqPmyx76O/Mgii6767JPWhf9fzN6QR8o38nTVj1ZB91K0ZBvL3DWMmBaVCwT7GS5y9aQUfkLN3bR6OZ/yRp/mXF829c5KUY/5Sa/3RSPRu1J6geV3WqpdiFyo14/vWzfdJu5lIV8FXel8mKi86chc6sFTHowvMXr2ESwTQMOd7sbHr+6sqpSvMP7ktq7xAGfIPWDkS8eZ2SGZaxCPZClH00moVMUtsER0mLbLiZi9u87FOejuefUI9QD3FdBinGn09oZdcPK5NrFXk1E/B1qwO+jufjhYOjuPRzD2JkykEha6Era0U9f17hqzZ2sw2S75Od1vOvyvZp4PnHNH9xn5qiGbZ0FkVeDrp50NqOZ/sYRmSiWqypnhpNWxEp8lJ03IIikdRD9ShTyz4zbOmcrsI3OKeQsULZh09oYnMVoE4//yY8/6SAr+sxfP/ZQ3jtRLBvb2fWQmfOijRrE0ZSXI/J+/ML0qZ6xrtoJkl19VZOidk+VbKPi66cxa+xdp4/UN1uohXobRw1mgaIL37WCpfyFc9HPmW2j3p/Q89fVPhOy/g3m+oZnJPPmDLgKyY0Ne8+SfbxlTqAdDt5JRR5eT7WLcnLcwoZE6t68nIMQOhdi8lQaP6C1L19Unj+6oQQz/YR59fbxlE0dQPCfQgARfaZZ56/Nv4aTQPEl1g1/g7XsA1Ks4dves2/Ij3/5hPg1BVGmgwc6flnLRwfD/bOTfT8E2SfqD5e/7UYY5HePsJ4uz6LNI2brHj42/edFzHUwkiKVUbQ2C00ommzfeLGtl5L54xlpAr4Ury9Q8nBaX2dclxycvR5wHeeaf7a+Gs0DRCebc42pYEQRUu2slF3LRyPIW+bKDreHMs+YpzVLZNrjQsA8raJ8ZjmP1VRPf9q4y/Gl7fNmrKQQFxTlefv+pHnPn9dL5YUMpHHxj1/i2v+grQtneMyS70ir6xlVMk+Yapn7Tz/saKL7rwlxymzfdwFnOqp0SxkxBc/Z5uRxm6iWVeaIq9C1uLGP2XAdwaaf9YyU2X7iHNESwcAMn1V7bWTJPuIiaMjE0xq9VoWVLxw5QSo2T4MJSeYRF/+y6sTdXDhsYv3w4hr/tPu6lk72ydrmdKbf/r1YXRlLXmfKjmJILJ4H8dLquyj9PPn+wBk55nnrwO+Gk0DHEX2CRu7Bb3krYTe9HFc30dnNsyiqceM2jv4QSVpUr/8xPP5OcLgA0HwFwCmyvUDvmJ8YV1A7dcT52Zj2T6uF3j+OcuoGQA1ubcs3pcqzT+l7FPdz7++5y8m+d+45VFc8YWH5H1qha/a0tn1fExWPHRx4x/P819s7R0085BH9x7HX/xgZ6uHMe85PFLE2//uYRwcnoKnyD5qY7fA0BqNs308hs5c2C2zHjPr6hmkFAY98Jm8jlqrAGHgChHPP7gtNlfpzFpVcYpvPbYfl37uweB8XhFcb6VRU/bxfJRdDzm79nYeVlXANyq9pE31rPL867R0ztnBJH98ohye71V7/mJCYSyskBafs2UYcjtMj+/ZO98Cvtr4LzJ+8tIAbnt0f+IG1pqQR/eewEtHxrDz8Jg0FMIoiB/bNGAr2m4tHM+XHnU9z58xFm75OK1+/oGRsYwgDnF4pIhLP/cg7tlxJPF8YbDzivGXnn8l7FMT1/yfOzAqryMvC91q/z+Fnn91b5+S49c1/nHN36Co5j/9rp4Jnr/M6gpknx2HRqvui7Z0Dn77jGHKicZMxCQhKpGrUj11ha/mZON4vtxNSFObXUfHAACjRQeu7/OGYoG+7yhZIbZVvStVHNdj6MiYIIoWTDHG8PcP7sGhkSKA6MQwvZ28RGAx8Px/se8EHI/hyEgp8Xwp+yjGfykPuApPtjtnS+O/d3ACo0UHA+Ph84nH1gt6C8km3MzFkOMtOR5ydm0zJCaKspLqqUomtpnOiFb386+d7ZPlk7ww/uuW5hMrfNU8f9kbKSvy/IP7hicrAIJVY6Rn0TzYxFcHfBcZslNjxY8U02gCHt17HK8OTuLlo+MAgNEpJ9hwm2vNZdeTTcVylhn0bU+xjaNtGshaRsTAHxsr43P37YJlEP7LpafL+4imn+0jtjl0fR/b9w8DCAKRtc43CBieDO6//JwVOL2/ACCs+O3KWTId8z999TFce/4aDIyFcogw/vVkH3EtwvhJz99l3PjX8/yDx8hUTwo1/4wZ9v1vRPVOXrWD2FnLgO8DL3DjrzZpS9rMxWNMrpQ6+LWs7AnqFx546RgA4PT+QmJfoFaijf8io8JbDRQdDz2wWzya+cf7v/YLAJC95UeKFXgeg81bCbs+wwjv3rikwPu2NzDUofE3I8Z/eKrCfwfPJzzkzmy11JIGEVi0uOYvjL/YYSqO6zNYpoENfYHB//SvbQIRIWMaUvPvztvwfIbRooMTkxXsHZzAsYjn37jFhZR97OqdvEqOj1wdJ0Rm+zih5i4MedpMHyA0/kEwnCV7/r4Pi68sHM/HjkPB6q9Y8ZTNXKplH8aYTI0VMZNNq7oAAN9/Ntiq5KyVXfK9rfDYTKtp/Qg0JxXhQdXq1NgOjBYd/OC5w3MStzhlaYd8DfFbeP4ml31GuNHuzWeCVM+Gnj+TqX5qqqcw/uL5hJHsztlwPFZVaNQI1/dlYHFosoJdx4LVS3xzdHm+Fxi7j162EU9+8nKs49duKztliXYFB4aCFgx7BycwMhWuJNJ4/uWY5y8MuusxlFxPTgpJSM1fae8gDGczxl+8pphokmIULo+ZGBS0jBZy3FTFlZOblZDn7/uK588nw/XLCshaBp49MIKunCX3KhDev8720cw6f3j7M7jzqYM17xde6lQl2SC0A3c+dRD//bvPYOfhsVl/7rNXdkX+HplyuFE15KbcwvPv6bDrpno+e2AEf/Ivz/Ft/AzkM2akeEoYUTEJCCMpDG6zur+QfUyD8NTrw/J4TdmH70mbsQz0d2Xl8axtyt70YiwHhwPjf2CoGHmOfKZxf6PQ8+cBXyvM9mkU8I1n+4gN3IH0er94HCC2iKwt+9g8W0ptGV1y/DDVs0ZvH9keQwZ8DZzF/5fOXNEl5SkxYWnjr5lVGGO454WjePzVEzXPCXdnal/P/7UTkwCAR/Ycn/XnVj3YNb15jBadIFWPG1XXVz1/G7ZRO+D7wEvH8C9PHcTxiTJs08CSjgyGeAAQUD1/Lvs4oecPNF/oFW4aQrLqdEV3Vu4wFUcEiOP05m0pRYmxvM49/zgiblSvxYMM+ArNX3b1ZCg31PxjqZ5EMM3mZR8xYVgm8c+shuxjip3CgvesN2+j4vmy1iHS0pnf9BmTcSC1ZuKcld0AAuMvCDubauOvmUWmKh4qnl9zmQ+E2myx0r7ZPsIQPbJ75sY/XnHr+AxnrujEd37/jThzRSdGiw7fjINkNa8w1r0dGdgW1UxzPD4RGHch+/R1ZuUxIDT6IzHNvytlTQAQTPi7eHDa9cNUT8H6ZYXaxt9Lrsrt7QhjQaJoSXTeFGzbsBQA5Kbk9VI9yzHNX/b2UYq8aiGuJdLYTXjxKdM8gdDzt4ygMC+xsZsXxECE7AOEsZ8J/h5GWjorvX0mYwFfADib6/5nreiUx8RkOx+6emrjv4AQnmQ94y++iO2o+W/fP4Qdh0al8X9i/9CMVjB/8YOdOOtT90YkMNfz0Z2zcckZfejJ2xiZCjx/kwcaPT80/t05i+fUJxu+ockwK8YyDPR1ZnBCKRwSaYAzkX1+vucErvrbh/DCwVHZN14Y17xtYnl3rub/gwgQx1mq9NfZ0BfEAZ5+fSRyzhevOx+3fXAbzjulF0D9ts7xbB+1TXPJ9ZvS/NXGbpkmstVUqUgE7uM4ng+br/BESwsxEY4nGH9V9okHfAHgovVLQQRccOoSeUx7/gCI6Goi2kVEe4joE60ax0JCGKVUnn8bGv9PfX8HPvm9F3BguIizVnSh4vp46JXBaT3XnoEJfOPn+wEAx8dDb1wE/YDAsx+ZqsD1Ay1YaP6jRYdv0h0cE3EU32f4/H27sHdwAgBwQvHybYuwrDODE5MVGcgdVjx/xphi/Lnsk+Iz2s8lsGcODMuNwoVBX9aZQWfWqqn5e1zmiNPbERr/Tat6AAAvHRmThtA0CMu7srj0zP5Iq4ZaSM+fGz4i3oLC56me9bJ9zNqN3TJNaP7CS7d4P6Ykqa5Y8dCRtWAYJCebnnzwXohq34Ii66jtHaYqbhA/USbTLWt68PSnrsAb1vbKY+L++ZDq2RLjT0QmgL8H8HYAmwD8FhFtasVYFhLS+NdY5gPhl6hUqW9Yfv+27fjeM7UDx9NlaLKCX/38T/HSkeaDtUfHSnju4Cgqro/rtq3DuqV5fPEnu2XWD2Os7sTHGMNXfroXX/3ZXlz/9SfkcZHZA4gmXMHXoidvY7zsouJ6srhIZPss4QbS5jn1APDikTF8+cE9+N7ThwAAJxR93zYMLCtkZdokoGT5eD7+6Rev4wv3vwKgtud/bKy6WGuAH9txaJSnKhrSq1xWyKA7Z2Gs5OL7zxzCt3/xWuSxTo1mbKrn39eVwXIeDF63pAN9nVn0d2ZDGUVpz1yLeIUvwHPnXT9Fnr8o8gr+X41pav6mlH2Iyz7V452suChkzEg1sJjwjo6VkOG1GgK1q+dk2UM+Y1bVHcS7lIaFbovU+APYBmAPY+xVxlgFwO0ArmnRWBYMQj6YrGMAKylkn/GSgx+/dAwPvjw9r7oeewYm8OrxSTytZKOkoeR4kRTD0/s78bHLzsSOQ2O4d8dRAMCXfrIHWz59X8SYqwxNVvBX976Mz97zMjyf4VPvPAdA1PiLjBkgMP6MBUVQssKX5/kLo5C1DPleigD0vuOBN672hrFNA33ciJ7gcpD4vADgyz/ZjWcPjACA3Apwz8CEnCCe3D+Ei//3A3iFp28KBngf/p2Hx8L2DtywLOvMoitnoeL6+NrDr+Lbj78eeazr+ZFGZQJV88+YhgxY9ndlsX5ZB1b25OT9oeefvrcPALkJu89Qt8I33tUzovlPx/gr7S/iTJU9dGSsyITYyz+Lo6MldOftiHGX7R14qqdojVEP4fkv5myfNQAOKH8f5MciENENRLSdiLYPDs6+IVpoCEMxPkPZRwT3DgwnZ3jMBJHtckypEk3D4Hj0/FOXdeDa89fgjOWd+Ov7X4HnM/wN95xHFKOqImIFN//6Fjzwx5fiTWf0AQg24RAEOf3B10IYweOTZaV4ysfIlCMDgcu7cxgYK4Mxhp9z4//q8UlUXD8SaLVMQh/3AgfHwywf4Umq74fw/P/gO8/gL3/4IgDglWPjYAxVKyaxGnjl2DiKFY+PM3jOpYVA9gGCiSTenVM0HIsjVjVEgZHayAOWy7uy+ItrNuN/Xbslcl1AtL2D5zPc9ewh+VlXEox/xjTkKi2d569k+xjRYrE0hJ5/2P4izmTFRSFrRiQZ8T9wbKwke/XHn9PjRV6q3l8LMeZ4r6FW0Crjn3TlVZ8GY+xWxthWxtjW/v7+kzCs9kZoyJNlt2YBlPT8E2SfA0NT+Oh3n8GL3MDEc7oFLx8dw8tHp5djL43/aHK/mVoID5co8LhW9+ZhGoQ/vuJM7BmYwPefOSTPrSX9COO/bf1SFLKWNOBRz9+Xudzii39iosLbOwSe/2jRkbr4iu4cyq6PgfEyntg3BCJg//HJiNcPBIHGZZ3Vnv/6ZYWqcQrNHwCe2DcEIPA8AeDgcPCZ7Dw8iif3D2FgvMwrUhl2HRuXsgYQaP5dStqokPrE/4CjrHJUhPEX7RNUz3/z6h5sWdMjzxWP9xRjeudTB/GHtz+Ld3/5EXz1Z3vx3MERmSorH2eSlCezdfP8o9k+hhHm2jeT7aNW+FqKVKcyVRGef3ish78Xw8qEL6BYwFftkVSL+ZTn36r2DgcBrFP+XgvgcIvGsmAQMoLPAs++I2EZWuFf0qQsmZ/uGsDdzx3GYV7ZeHyijGLFi3R9BIBPfW8HLJPwpd+6AF//+T788RVnRvKf04xRbRGQhkF+/jXnrsZI0ZEe1NVbVmLLmm78v//+kjx3spy8qhFVqmuXBBksicaftzyI32+p7R2mKlIOEJWb9+08irLr41fO6seDuwbxYqwAzTYNLOsMDMmJiSDoO1p08MYNy2QlrkB4/kBg7AfGSzjCjf/rfFX28X95HpNlF0XHw0Xrl+DxV4fk6wgveVkhE3muouPh2QMj+I1bfo6evI2S42PT6u6q92kJn/SEcT1T8fzjSNmHG9PJsovP/8cunL2yC+MlF5+95+WqaxKPEyujeqmeSXv4zqS9g4iJJOX5T5Zdvn9wtewDhDUPKgYFsaTJspv4fYtjzyPZp1XG/0kAG4loA4BDAK4D8P4WjWXBoGriE6Xkf0axN2yS7HOQG/3tr4V6/KGRKZyxPFr1enSshI6MiQdeOoav/HQv3rFlFX5pbQ/SIDJgjtbx/F87MSnTFAXC8//zd56D5V3hcSLCH195Fn7vG0/KY5NlF3/9H7twxaYVkUyL14emsLwrKyezjkzQmC0S8OXpfkCY6QGEPWW8mOYv9O+Hec3BO35pFR7cNYgnXxuKXJPFi7wMCibVsZIDnwEb+hM8/2z0c3v6tRH5fr0+NIXXTkxK+YcI+K2L1mF40gk8f5Pk6mpZIRtZRZQcH6+dmITPwlVikucvAr7CuG5Z04PrLlqHt521vOpcOxbw/bdnDmFgvIxbfvsCXHDKEhQdD9tfG66SOTKWIeXJerKPeP5IY7dp5Pmrmn9Qr1Hb81drP9T4R9zzF+PxGUPR8bAsFtxNIrvYUz0ZYy6APwBwH4CXANzBGNM7jMwQNYBYL7cbSJZ9Dg2HMo8Iwh0YKuL5gyO45suPYLQYpCQOjpcxMuXINgeHRhrHBu7beRT/464dcowD49WaP2MM//uel/Crf/0zvO/WxyOrk4GxMgwKDFqct53Zj4vWh7nUgxNlfOkne/DuL/888iV/fWhK9u4BgomjO29XB3xjsg8QasXBOENDIIz/L149gZxt4BIeRxBN1VZ0B+PN8MljaSGD4xMVaXw3cNmnM2vhq//5Qlx6Zn9VwPXp14dxZLQor+EeHuAWY1nencN124KF9O5jE/J6lnZWe/7xVVG9VE/hpWYtE599zxtk7x8VYVSFhn7vjiM4rb+AC09dAsMgFLIWLj2zH2/e2Bd9XYMwUQ7G2Uy2jxXJ859Gha/I9uGTlfj/YLxQqyrbR3EA4po/IIw/Unv+YsyLusiLMfbvjLEzGWOnM8ZubtU4FhLDqudfw/jXa+wmGlkBwLYNywAEQd//+8g+PHdwFDsPjWK87KLsBrnuYqVxcLiIu549hFd5fnsSP3z+CP7x8dekBzs0Wamqrv3JywP4h5+9iktOX4Z9xyfx1Z/tBRB448fGSujrzCYul4kIt/z2hfjG714EAJH+9f+q9Dl6/UTU+AOBER+rIfv05m3phQeef/h1EQZyeVcWREHnzPXLCljVnUPeNvEUXz2JjplCHllWyOLERFlOgv1dWXRmLZyxvBNXb1mJ2z64LZISuXlNN556bVjKPkdGi7j72cOR61jRncOvnx/mSwjj31fIVsktI8XgddcuyUfGpSImH9tqbKDEBPFX976MG7/zNB5/dQhv37KyYatly1Rkn7rZPtUVvvY0Uj0NNc+ft+TYfWwcm/7HfXjh4ChKjg/GgHzGihjmRp4/kcjzT6f5i7EvWs9fMzeMTFWkpymCaU/uH8K7vvQwntw/JHegAkLNX+1lc2i4KI3FRacuQdYy8NKRMJVy34lJmXVTdn2ZY753cAIf++dncduj+2uO7dDwFBgDdhwelcce3XMCewaCCcPxfNz87y/htL4Cvv67F+GqzSvwjZ/vx4GhKWz+9H34ycsDWKHIQHH6u7K44JTA+z86Fk5i9+48ysfr4chYCacsixr/Ks+ft/UFAkNx5eaV8n1Sv9xCC7ZNA308kHtafwGGQbiItz4Agtz44LnCIOzxibIM5K5bmsdp/QU5diD0dld0Z7Ftw1I8e2AEUxUPZ63ogs+CeoLfvWS91OCXd2XR25HBHf/ll/EPv3OhnMyWKgFfwRCX3c5YHuj4SUbINg105axUsoq4riOjJfzo+SPwfIa3b1nV8HEZJeCbtrcPUTDRh8HbZjz/cC8Bked//0vHUPF87Dg8KtszFLJRz78rZ8liriTN3zSIp3q2X8BXG/8FxPBkRRqbibKLFw6O4re/9gvsODSGr/50b6SqMZAAXLzt8w/iKz/di7LrYWC8jHe9YTW6shYuXL8Ea5fkcefTh2QAcd/gZCTlUlSX/nTXIBiD9E49n2F3LIh5mHvj4yVXGsvf/9Z2vOtLD+Onuwbw4xeP4dXBSfzp1WfBNg28ccMyjBYdPLhrABXXx4nJSmLAUUWk2onXMiiMMRwaLoIxNPb8PRbxht91bmDIHt17Au/duhZ/dMWZ2HrqErxBiXGIoK/w8kX9ABB6jsKQnr2yG88eGMEtD+7Bm8/owxnLu/DPN/wyPvH2syPP97uXrMd3PnwxLjm9T07Qop9OT97G+y5ah808WCsmxW0blmLd0g5pWJYpqZ6Cockgc0lkGdUqNlpayKQyrqoRIwLe9YZVclz1UFthp+nnX3H9sEp3GgFf8ZEG7S+ClhwPvxLEaY6MFDElduKK5fnnbBN5PjnV1vyDLrkd2fYK+Grjv0BwPR9jJVcu5yfKLv55++swDcJvv/EUPLhrINKZsVjx8P89vA8HhoqBpswN5vmn9OL5z1yJS07vw+WbVqCvkME1563G2Su7sO941PiLegBh9I/ylcAPnz+MK//2ITkBVFw/kt1zDm945fkMnVkbH/mnp/HVh17Fyu4crtgUeNoiEHr/i8fk45Z31zf+Yp9UoY9v6CvIXjpi3PHVQ0/M83eUVE8AeDPX8JcVMujIWPjoZRvxrx+5JBKMFrr/hr7Amz5zRRc+/Wub8JG3nS4NhpCS/ujKM7G+r4Cxkosbf+UMAEFb5Mj+rgbhM+/ejNP7O3HR+iXS2L3pjGUwCLj+l09FIWvhwlOXoDNrySwiwXc+fDE++Y5zgq0DrWhV6tBUBR22Kf9PpmpUevd2ZCKPq4VaJPapd27Cl99/Qardtdbw1wfqyz6mEvAVcozU/Kfh+Yv2EOMlR0pzh0ZKkT14VdknYxrSo++uIfuUXQ+Ox2Q753poz38BsuvoOD5/366WbYwudmsSaYxjRQf37jiKXz1nOf7rpafDZ8DtT4R1dQPjZfzDQ4Gmvv/4pNT71/bm5Zf3prefg0dvugx/d935OK2/UGX81fYFQDgJvHhkDIwBD7w8ACDI7FHflk2rAs9weVcWd37kl8HA8NyBEbznwjXyS3Ea96Iff/WELFY6ra8TjejMWnIcG/oKOD5ZkcE8cb+KaH+w8/AoJsuu7IwpsE0DP/rom3HnRy6p+Zpxzx8Afu9NG/BnV58tjb+YUDqzFr71wW342/edh4tPW1r9ZDE6MhbO583TtqzpwQ//+1vw0cs2AgA+/NbTcO/H3lLloZ+5ogsffutp8u8NfQWcxXP1hyYryGdMrOkNjG9SywgAuOzs5VVB2iTU90o8ZxrUNsdp+vk7HlP688zA8+eyz6uDk6h4PjKmgcMjxcgevOJ1bJNgGCTHV8vzF4/Npwj4ZnWR18LjB88dxpcf3CO3vzvZiACi8OgeeHkAxycqeOcvrcK6pR1Y3pXFHiUge3C4iKmKh43LO/Ha0JTcrEP1yFQ29BXw+tCU9O6TOD5RhuP52Dco5KDA+B+MZQOt7ytg7ZI8PvjmDTh1WQEfu/xM2CbhvReGpR9rl3TILfc2r+7Gz/7kbfjdN61v+D4UsqYMJG7oK6DiBi2uxbFCzPj35G0MTVbwzi8+gr/8wYu8d3/0a7F5dU9ipovgFC61nJ6QttkTy5wR13bt+WtS7z/7q2evQFfOwvKuHDat7pariKxlysm+Ht+/8U34s7efBSAw/h0ZE6ul8U+utP7oZRvxJ1ednXifivpera3xv5OEiDkASNXVM3itmOwzHc/fNOT715W1cOlZ/TgyWpSdXQsZM6wj4OdJz79Gnr/830oV8BUrkNabXr2H7ywhqjanKm6Vd3kyEC0NVvbkYBqEh3cfR9Yy8Cs8N7sza8lzhFEFgLed1Y+vPbwP2/cPgwhY1VPL+HfC9RmeeT04T90s5NhYGRnLQIVXur7Ke9ts3z+M8ZIjU0jPWN6JPQMTWFrI4Gd/8iuyN8p/eetpeM8FayO7SZkG4dRlBewZmMDp/Z2yOrYRan8VIcOcmKhI7yz+2aje3BE+sTWzQxQAvP+Np+DC9Usi3TAF/Xzc8UmnGT78lg34zQvXNuXpquRsU74vw5MVnLKsICf5Wn2Q0qJ6/s0Y//Sef1QOAzC9Ii/hzRthoPnXL1iDvG3iZ68MymOq5i8qj+tp/qaSsppG8y9kLRiULpNqrmn99LNAEJt0JOXPnwyGJ/mm4h1hkO/CU5eEBU1ZU64OxD+xQZD9bf79hSM4a0VXzS+UkDSe3D8sg8pA4BUDwBt5MPLQcBGvnZjEeet64foMj+49ISUlIXMsLWRgGiQ9XyKKGP74ayZ51LUQRjZjGVjdG8gxJybLstldIdZ/Rf1Cb+CZQGaTXlkha0WydVQuPm0p/vFD23BuyiK4JCzTSHx/mkEY2EmelZKmICkNarZQknGshRp4rxfwVaVxtUoXaNL4ixRL08CT+4NMq/e/8RSs7s2j4vqyj1UhW+3556XmX23ciUimVXfUmcQE77lwLb75e9tS1QTMNa0fwQJBBBZrBdDmGmHYl3RkZNxhm5JyWMhYMkDbnbdxfKKCNUvy2Mg9sMmKh0vPqt0/afPqbr4TVRmn9Rdk8PhNZ/ShrzODt29ZhYd3H8f214bgeAzvuWANXjwyhif2DWGs6GB5VxYbeaVwWsMjdP/T+htr/fI6ufHvzlkyq+j4REV+QeOdF1WDJTbwaNbzrwcR4S0bW9+XSm3R0cFbD3/hfefirBWNM3PqoUpXaWUsICrn1Hu/iYIe+RXPV3L1m0/1VDOFvvC+8/DkviGcvbJb9q/afSyQRDsylnwdIUcJzz+eNgsEk9OU1PwbG/+evI23ntn6/wdAG/9ZQwQ/W2X85daCBVsGf7etV4x/1pLapNAuT10aFCUJyeZtZ1aX7wtyton/54qN+OT3dgTtbXmgdEV3Fh9687kY5a//2N5g/+CzV3XjvHW9eHL/EHK2iTVL8rj2vKAQSQ2M1uPcdb3I2eFG2GnozIb6rNpLZ7LsVmVyANEMDhEUng8FOLNNXvFKxe1fP39tq4YTodGk0dNhY3C8LBuuzbSl81WbV+IqXr+ximdqiXhY4PkHjwk1fwtdWSsxQ8cgkqnQzUxG84H2Gu08RuSTq1sCnkyGpyqwDIr0hTlfkSLUAhTh7Z6yrAOGQTh1aQc6sxa2rk+WLgTv27oOV2xagT+8bCN6eP66KH/vzlvI2QYe5cZ/Q18B29YvxY5Do9i+fwiXnL4MPR02rr9kfWoP8e1bVuIXN10uPfg0CM++K2/LHjVDk2VMlN1E3f3CU5fgw2/ZgI6MKSfutE3q2gk1qJqmGKlZlnSkl3wE3/tvl+DTv9Z4DyexUhTeu/ifa0a6Eo358jFpRmQo7T42AaJAgop7/iu6czUTIQLjH/zfzOaK8WSgPf9ZoOR4UlZonewTNBsjImxe3Y3dAxORZaga6BTGfz3XuP/T1nUoOV5Dz8UyDXztA1sBAH//0z04gKIsYhIG3fMZVvXksKyQwUUblsJ/ELzW4NSmr4mI5CSTFlX2yVomurKWlH2SAvE528Qn37kJ9+48KuMC7fYlTkPE859l43/nRy6pKp5Lw/mnLIk4KLUQLabFqu2UZR348R+9Fac3IQcaBuGbv7dN1pgIejts9HYEezV38JVhXPP/+FVnouycUeN5VbmwvZwGbfxnAbV3e6sCviNTFZlt8v0b3xRp2wAgEmASgatTlgbyi5oTnhbhfam9T37zwrV49sAI/uY/nQciwoWnBgVKl5+zQqYWzjWFbDQtT+ybO1nD8xdkzHBHrmYDvu1ALiL7zO7X/sJTGxvwmbCUy3eqHBfvNJuGpLoF4Sz9fM8J+R2JZxN1ZCwkJHIBiHr+083GahXa+AM4ODyF93/tF/jOh9+YKm86jrpRdysDvmLpbZsG4okHapbLmt4OEKEpLT2OWD2o6Y3/69pfipzTmbVw2we3YePy9B7aTJGeP5/glnUGjdRcj1Vl+qhkLHNBe/5yJ7JYj6J2YGnM859ttqzuwc/3nJAVzVL2qZOFJDAoTJtut1iRNv4ItsB7fWgK+45PTs/4T4aef6s0/5Epp24hkur1Xn7Ocly1eUXqwGsS3XkblkENC1tEKunJolPKPtzzL2Tw2okpmAbVXX1kLEPWQcyHApy5IG+bGC+7sy77zDVLZykttRZiQxuRktxMQFkNX7Wb7NNeo50jRBaMk7DBQxqOK57/bMg+k2UXX7j/larxDIyX8Md3PJf4Gqrnn4RqpLOW2VT6ZBLvesMq3PDW05pK7zsZiICvyOLp68piYLzENf/aRi9rGtLzr9XsrN3JKZvYtBPC+I8V58axUrelBMIVRpreRup+v+0m+7TXaOcIEaxN2totDRHZp87G6Gl5dO8J/N0Du7Hj0Gjk+EOvHMedTx+Ue+yqjEw5iRWmAlXzn43qwjed0Yc/vbpx+f/JRqxwRGvqVd05DE85GJ6s1Nf8rVDzX4iyDxA2UGtf4z+zauRabIjtoyyyitIYc7VHj5Z92pCJGXr+JybKyNsmLJNmxfN3amy4cpR3qxwrRb8ExYqHsutHgq9xVMPXTE+UdiMe8F3B87jHa2T7CNSWFwtZ9gHSNSCbTwjjX5nm97MRhkF45xtWyeZ3sr1DCs0/Ivu0meffXv8Fc4Tw/N3pev6TFSwtZOD5bFY0f2H845usHx4Ne+KrqNW9tVCDne32T9oMomWzaLMsiniA+v11VC+v3Ty4tIiMnzRtCOYTc635A8Dfv/8CeXvask+bOVUzGi0RvZeIdhKRT0RbY/fdRER7iGgXEV2lHL+QiF7g932R5oFoLIxpLc/i9ider9n6FgiCvF05K1IoNBPElnXFSnQ8R3hASl3+fv+ZQ7jksz8BUL/QRpV92u2ftBnOXNGF+z72VtlraKXSd7+e559RvLyFWOQFKMa/zWSf2epDlBaTmjD+yimLLeC7A8BvAHhIPUhEmwBcB2AzgKsB3EJE4j/uKwBuALCR/1w9wzHMmFDzrzb+YyUHn/i3F/CD5w7XfLznM5gGIZ8xZ0X2ETscxWWfIwme/w+fD8dVT/PvXCSyDxCksAqfYmVPSuOvvCcLNeAbyj7tZfzr/V/PBbK9QxOeP9H82KClGWZkBRhjLzHGdiXcdQ2A2xljZcbYPgB7AGwjolUAuhljj7Gg+9i3AFw7kzHMBkLzT5J9xLF6eqPrM1gGzcjz//x9u3Af32+2luwTGv/ohuNA4M3VS90U3p5l0JzlS89HunK2NPppZR97gWr+YcC3vdTek51FYzTj+cuNX9rvf2auRrwGwAHl74P82Bp+O348ESK6gYi2E9H2wcHBORkoUO35f+6+l/G733gCQLjBuVcnHhB6/ta0s31uf/IAfsy3LBSBR9X4T1Vc2XtdDfgeHS3h8nNWYOdfXFV3g3Nh+Nrxn3SmiE3t6xV5qV/0Be/5t5nmf7JpZqcw4Ue142q64YiJ6MdEtCPh55p6D0s4xuocT4QxditjbCtjbGt//9y1QRWetPDu9x2fxD6+IYkw/q5f2/iLTb87bBPFaQZ8Xd+XryWzfZRVhNiUPBhv+BpHRktY1ZNrmG8vDF+75SLPBmKDmvqav+L5L1Tjn2lP2UegBu/nEuHNpzHo8TbT7UTD9R9j7PJpPO9BAOuUv9cCOMyPr004Pmfct/MounIWLjm9dqXpeCzbx/NZeJsJ419b9hGevyr73LH9ANYvK0R66tfDcX35Wg4P+Jbc0PgfHQ2Nvwj4itXAyhRfigwv71+Mnr94fxr19hEsxN4+QJi62G4BXwB4+X9eHcmsmUviO3nVQ8s+1dwN4DoiyhLRBgSB3ScYY0cAjBPRxTzL5wMA7pqjMQAItPR/fOy1uufE8/w9n1XJPXU9f9+HZUYDvn97/yu47bH9qcfp+Ey+hiMCvkq2z2Ge4792SV56/iIGIHasqgcRoZC1UumYCw2R8ZPW81+oqZ7BJi7tKfvkbPOkrVrNJjx/amPZZ0aRHyL6dQBfAtAP4EdE9Cxj7CrG2E4iugPAiwBcADcyxoQb+xEA3wSQB3AP/5kzxEYl9YhX+LqKIRYefxrNX/X8Kx5rqiLR9Xz5GklFXse4od+4vFP2IBGrgZXd6TpmFjLmgpU06nHuul4sK2Tq7gsQlX3a74uchvddtA5nLO9cVAH/6SDz/OtsLC8Qq4R2/F7NyPgzxr4H4Hs17rsZwM0Jx7cD2DKT120Gm28BV4ugMCswslHPP7jtszSef5Dtk89YKDoefP54sbtWIzyfwWfha0jZRzH+kxUPGdNAX2cWLx8dBxB6/mm10A6+efRi44pNK3DFpivqnrMYUj1PXVbAqcum38xvsRDv51+PUPNvP4ehvXK+pkEjz194/UDU+LuxQG9azR8ItHrXYxgpVmo+RkW8bnyiUY1/2fWQtQx05225ohDtHtJo/kCgeXt1rmMxYy+CVE9NOpZ3ZWEQUu1BIWSfdlwtLnjjn7WMiIGPEzX+ofGVmn/sdxKB529I4z9V8eA04fnHJ5pKguxTcX1kLANdOQuTFQ+u5+PwaAlLC5nIRh31WNJht2yzmflOdhF4/pp0nLqsgOc/c1XdGJEgzAxqv/+ZBW/8bdOo27BtolTf8w/TL9No/sHbWax48HyGkuPC9fyGS0Ih8wiv3E1I9Sy7fuD584ZlE2UXA2MlLO9Kv7/tZ35ts8wo0kRRNf92q9TUzD5pDD8Q5vlrz38ekjEbyT6hd64afz/mjdf3/H1Z4Qtwz59PFmMlt2FjKkca/ehEU6rh+QNBrn/R8eqmL8ZZP4PNWxY6iyHgq5l9hKPQjqvFBf9f3kjzH1M8/0iev8/AWDgJ1Fs9eB6DwXv7ANH2C6LjZj3E6wrNvyLbO4SvGWj+ptykZKzkwPFYW2YZzEdEcK8de7RoWgfpPP/5S8Yy6ko2QvaxDJJGV3j7agZOY82fpG6s9vdJo/s7sdd1EzT/cszzHyu6cDy/Lf/p5iPC89fBXk0zLOj2Du2ObRoop8j2WVLIhFk3SoZPXP5JQmj+QttXjfZoiowfx0uOL8QDvqrmP15ytPGfRYTxb8flu6Z1tHN7hwVvObKWgYpbO8NF7Nvam7el/CILu9SUzxRdPYUEo2r1aTx/t0rzr87zL7s+snZo/MdKLlwt+8wawvhryUfTDLq9wzwmY9Uv8hJedkfWkuepzdzSNHYLPH9D/gMUm5V93Kjmn2T8K66PjGkglzHkfZUUmUSadIhlezt+iTWtw2iiIGy+0X4jbhJ1b9bB8TLe+9VHI7tyifTKvG1I716kQ3pedb5/EqK3j1j6qXLNSIoWDzLbJyb7OB6TE4EI+Ip/Msfz4Xh+W/7TzUdEz6OF2tdHMze0c6pn+424STKmKRu1vXhkDE/uH8ZLR8bk/cLg5mwz1N6TevykyPO3kzT/JrJ9vASJSXj/ItVTyBMV19eyzyxia89fMw205j+PUY2lSMFUA8Cez2BQsGyLZ90EPXcat3eQmj/PFClVmvT85esGvyvKRCPSPUWRlx3z/LXsMzvogK9mOrRze4f2G3GTSOPv+bIVsmr8RWsG2zISeuz4DVM9fZ+BMfBsn+A/YbqpnmJ+qef5C1mi4jEZB9DMnIyWfTTTQLZ3aMNW6e034iYRPTcinr8iywjJJvD8q6t6RUygVq2AONeqIfuk8fzjWUaO50sjJJ4r8PxNEJEsXHN9LfvMFqHxX/BfCc0sInr/t6PTsOD/05M8/5Lq+XuBZGMZFLZ3iDR4C86r5fmL40G2j0j1DB6UMQ2ZSloPJ5Zl5HhMFnOJzKGy68lrERKVzvOfPcQKSss+mmYQvkI7fg/bb8RNIgym4yqyT8Tz92GaxGWfOp5/Dc1feOtWpMgreJ2cXb+pnMCJpZM6no8uns9f4vsDOB6TGSm2Sai4PhyPac1/lgiNv34/NekhLfvMX8SMXPF8jCUEfB0erFUDvnLfXq8Zzz8s8hLeeiFryY6d9XCrPH8f3Xnu+fN8fiDcWcg2DRlXaMdWsvMRg39+dhsu3zWtI0z1bL//mwVv/IVHV3GTA76ex1szqLJPgudfK9VTav6mku3DZZ98xkTFYzgwNIV3/N3DGBwv40fPH8GOQ6OR54i/rusxWclbcjw5XnEtGcvAVCW4lnZcbs5XMqahZR9NU8hUzzaMFc1oxET0OSJ6mYieJ6LvEVGvct9NRLSHiHYR0VXK8QuJ6AV+3xdJrJvmiKjmLzz/UPZRs31cL+jkGVb1htk+tVI9Vc/fMAgGAVNcVurImHA8Hy8fHceLR8bwyrFxfPrunfiHh16NPEdcbqp4vtT8S44vx5vlm7ZkTAOT3PPXMsXskVFSaTWaNMj2DotQ9rkfwBbG2BsAvALgJgAgok0ArgOwGcDVAG4hIrHd1FcA3ABgI/+5eoZjqEs0z19o/mqevx9INryrpyrviOIwcTsJNdsHCIyxyPPP26YMzALAaNHBWNGJVBgDSQHfUPOfqniyJXVWKUSa4oFkLfvMHhnL0L19NE3Rzjt5zcj4M8b+gzEm0lkeB7CW374GwO2MsTJjbB+APQC2EdEqAN2MsccYYwzAtwBcO5MxNEKVfUQHz6o8f5MisQH1vka9fURmkGmEmTgiPTOfsVBxfWm8B8fLqHg+BsfLkedQK3zFZu7LOoMNYMZKjhyv0PwzVuj5a0919gjqKPT7qUmPbu8Q8EEA9/DbawAcUO47yI+t4bfjxxMhohuIaDsRbR8cHJzWoJI9/2iev2WQXLapTdk8n0WCv0mo2T5AoP0L41/ImHB9JmWbg8NTAFDt+SuSkji3O2fDNgkjU46cPMLmY4Qi1/y17DN7FDKW3JBHo0mDoaz4242GewAS0Y8BrEy465OMsbv4OZ8E4AL4tnhYwvmszvFEGGO3ArgVALZu3TqtzWeTNf+od28aYeVsKXaf56XX/IEg8CNlH25IJsvB3weGigACKWei7Mp9QkVXTyBaI9CTz2C0WO3526aBibLw/NtvuTlf+av3vEHGWjSaNIiIZTvKPg3/0xljl9e7n4iuB/AuAJdxKQcIPPp1ymlrARzmx9cmHJ8zxHJsouTKwKoa8BWev5gkSrEagEbtHeKaf8YkDE+Fmj8Q7hlwcGRKPu7YWAmd/Z38OcKJRawaLJPQk7cwVnTkSiVr8YCvku2j2zvMHueu6231EDRthrlY+/kT0dUA/gzAuxljU8pddwO4joiyRLQBQWD3CcbYEQDjRHQxz/L5AIC7ZjKGRgjjeHwy1NmrPX+lNUNE9lF77AeZQHGqPH/TkMfEhu4T3FAfHC7Kxw2MheNxIo3cQi2/J29jpFiRcQi1wndKZ/toNC0n7OrZft/Dma5xvwwgC+B+nrH5OGPsvzLGdhLRHQBeRCAH3cgYE1b1IwC+CSCPIEZwT9WzziKiKvbERNhaOZ7tI9o7APFVgR8J9PoMiK/uhKEX+eFqnng+E7y9U1yiUZu8DYyHur+T0MjNNgm9HRkMjJfkeMMK3/AfTcs+Gk3raOcirxkZf8bYGXXuuxnAzQnHtwPYMpPXbQbhLQ9NBsafKGrgHV7kFco+0VWBrxh/x/NhGtGAoOtXZ/sIOjJR2UdF9fyTungKz3/3wHiV56/mFGvZR6NpHbK9Qxt+D9tvxE0ivOTjE4GxXdKRiRh4j6d6ihS/eLaP6vkn6f5eVZ5/6AEI4z8eM/4Zy4hk/Dh+dcBXGP/RKScs8uKav+pltGNxiUazUGjnPXwXfGpDJib79HVmqip8Ix051fuUbRzFuXFEsFbN9hGIgK8Izopjy7uzGFBy/dX+P6rs0523MVZyUaxEPf+sYvDbsZWsRrNQEF+/dmwL0n7TVZNYBoEolH36u7Kxnbz8SJ5/fFWgGv/dx8bx1GvDkeePe/5R2SeYW0VaJgB05y2s6MpFPH91Uikqsk9vPqjyPcFXLcma/4L/CDWaeYvewH0eQxRk8pzg2T79nVHjL/r5i6Zs6kYsbkz2+c2vPob3fOXRSBzArcr2UQO+wXOqmn93zkZvh41RZZOXaMCXF41x2QeAXCUkGf92bCWr0SwU2ln2ab8RT4Ms36UraxlY1pmtrvA1w3bM8V7/foLU86KyAbwoAhNyj0j5IgJyXKOfUo1/3o5sGQnUzvYRxl+sEmSqp5Z9NJp5gZZ95jnCWPZ3ZZGzjaoN3E3DkEa7VMfzF4b253uOR84BQs9fVPrZvFMoANlTCAC6cxZsgyK5/W5Cnn/GNNDTERj/QS77hO0dtOyj0cwHDJ3tM79RjX/WCvrtiPRKV9nMBYjKPmo/fyDM3nlEMf5Vef58BWAqzzlZUTV/G7ZpRNI7o9k+YfGW0PwHxsrIWIaSVhZ6GVr20Whah9D829EJW/DZPkD4wSzvykrdvOz6shrXNAi2Fd1/F+C9fRTVRxjxh3cfx5ZP34d//+hbqrN9lGIv8bpq0Lgnb8PxWMTgq9k+xQTZZ3C8LPv6qNcDaNlHo2klV25agcmyi16+Sm8n2m+6mgZRzz80/kCgtwcVvkm9faKev+czXLR+Ca67aB0myi72Hp+ome1jmwYyVmiYRcMw0a3TibSOrg742qaBbm78K54fSe9UvX2d56/RtI51Szvw0cs2Yo73pJoTFoXlEAa5vzMnd8MSuf7C80+SfeJ5/gBwen8nfv8tpwEAxopOzWwfS+kXBAB9nVkAQaqnZRgRnd/xmAwcqRW+OdtEzha5/WFlcSTbpw2XmxqNpvUsCsthJ3n+TlTzF7JPvO9P3PjnbFPKMWMlV/H8o9k+ceO/bmkH3nvhWlx65nLYFlVl++T4pBR6/sF41vTmASCyw1RGyz4ajWaGLArjL7Y/FAFfIJR9ZLZPguwTz/YBAuMvJJwkz18YZss0IvJM3jbwufeei7NWdsE2oqmerscU4x/doevjV54FAHh9KGyaKp6XCHrbQY1GMy0WRcBXGMvlXVnZ40fIPq7vwzJD2afkxjX/uPEP5JisZWCs6KDAM4Bkbx+jOuAbjCGUbSyT4DPA9xkMg+D4PnKx/QTEY6/eshLnru3Bar4CUO+zTaMttUaNRtN6FpXx7+/Khls5Rjz/UPaZqkQ9/7jxF/16gr47Dvq7Ai3flFk+3DAbRkSeiTRj48cd30fWMKOyjxtu5gIEFcrfv/FNkTGI59J6v0ajmS6LwnoIY7msMyNTJoWH7foMtkFSDpoqV3v+aqaNMNLdOQtjRTch2yf4HWwQExp89TnEcVHo5XpMBqJFV1HVsBNRxMMXMYx2rCrUaDTzg0Vh/DOWid4OG1nLjAR8fZ+BsaAXvzDWU05YjevygG82ot0HRrqHe/7V2T7hJusmbyoHxIO0wW1R6BV4/tHGcvUCuVlF9tFoNJrpsChkn8vOXo7VvTkAiAR85f673IPOWmaV5+/63CvnclEuE8o+w5OVhGyfcBIgCmIJZdePtmTgk4nw/B2PyT5ARceDaVDdbeHE47Xso9FopsuiMP7Xnr8G12INAChFXl7V/rtZy8Ck0nvf9Rh8FpN9+O3unI39xyflBGLEPHw1+6fs+tHCLEPIPjzd1PORF/v9ll25uqiFbWrZR6PRzIwZuY5E9D+J6HkiepaI/oOIViv33UREe4hoFxFdpRy/kIhe4Pd9kU5yuorQ/MuuD8ePSixZy4jILp7PAj1elX2k52/xPH+f7xkQzfYRur700tVOnKaQfRTPn49rouTK27WQz609f41GM01maj0+xxh7A2PsPAA/BPA/AICINgG4DsBmAFcDuIWIhDv7FQA3ANjIf66e4RiaQso+jifbMQsvPad43BnLgMcCz19N0wwDvnaQ58/3ABaERV6h9i+eTyADvr6PybIbZP0oso9azZt8DVrz12g0M2NG1oMxNqb8WQAg8iKvAXA7Y6zMGNsHYA+AbUS0CkA3Y+wxxhgD8C0A185kDM0iJJXJihdq/ka1gc5ahizyqhXwdX2G8bIbCc5mzKjRFwY6mvYZ3H5k93Fs/vR9YAwRb1+sLmphx15Do9FommXGmj8R3QzgAwBGAfwKP7wGwOPKaQf5MYffjh+v9dw3IFgl4JRTTpnpUAEEhrUrZ2FgrKRo/rx/juL5Zy0Tnlcn1ZO3eBiaqMQ8/zDVE6i/AcvewYmq5w1uN5J9tOev0WhmRkPrQUQ/JqIdCT/XAABj7JOMsXUAvg3gD8TDEp6K1TmeCGPsVsbYVsbY1v7+/sZXk5I1vXkcGinJbpqq5i/IcM/f81lkUhCGuTvHjf9UJZKZI2WfmMef5Pmrk4Yq9eQayD4ZS3v+Go1mZjT0/Bljl6d8ru8A+BGATyPw6Ncp960FcJgfX5tw/KSyujePwyPFqmyfXMTzN2Rjt1yC7NOdD9664clKrOma2MkrKvsk7b6l7u17QOndk1720Z6/RqOZHjPN9tmo/PluAC/z23cDuI6IskS0AUFg9wnG2BEA40R0Mc/y+QCAu2YyhumwujeHw6PFhDx/RfO3Q88/k1jhG3j+w1OViOYf7+6ZFPAVrzep1BRs27A0fO1Gnr82/hqNZobMVPP/LBGdBcAH8BqA/woAjLGdRHQHgBcBuABuZIwJS/cRAN8EkAdwD/85qazuzWNkysFY0QEQGuyI7MN3+QoCvtXZPqKt84nJimy7DET7+QNKwDch20fs7fvkJy9HV87Cp+/eCSCN5x9NJ9VoNJpmmZHxZ4y9p859NwO4OeH4dgBbZvK6M0UY6wPDRQBqkVd0wxSX7+QlagMypiHPFQFfxpCY7WPFPP4kzV/IPl05S24EDSAiMyVhmQYMQt0qYI1Go6nHorQeoj2y0NktqflHN2IRjd2E4VazcHrytuzbUy/PP5Pg+Yv7JpUmbuoEkmtQ4QvwbSK18ddoNNNkUVoPYfxfOzEJIGzHLDx/0wiasgnNP9jjlyJyjGkQlnZkAITGHGhO9pksu7BNgmEEP2IyaST7AMGEoWUfjUYzXRal8V/RlYVpkNwdS6Z62mEKZtDewYfHGG+0RlUe+dJCRp4vyMRSPe2Ealxxe6LsRqQmk1v/RrIPEMhOXTzorNFoNM2yKBq7xbFMAyu6sjgwFNf8Q+NvGCQ3cA8mA6Oq4dqyzgx2D0QbrFmxYGzSxiuW4vkXsuFHIFYb2RSyzzd+7yIs45OPRqPRNMui9PwBoLcjgxOTwZaOQrYRnr0lPf8g20d4/nGjvKzAd/FKSvWMZRBFZZ+wuVw2ofK3UVdPADhzRReWdWbTXq5Go9FEWLTGv5A1ZQfPJM/fNAiO5/PNXrjmH2u7sKxTaP61s32EoU8y8vHjScVmGo1GMxcsYuMfyi1he4cw4GsZhArf59ekYDKopfkzpUFFrYBv0mYuQHRFIIx/PrNoPxaNRnOSWLRWppCJau2AmuppwDQMVPhmK6ZZS/MPZJexkiOPqTt5ATWyfZTsoEjAV8hPDSp8NRqNZqYsXuOfjRZ0AaEhNozAcy8rG7uc1l/A6f2dkecQAdfRYmj8e/MZXHjqEmxZ3Q0g7PWT1N4heM1qOUjLPhqNZq5ZlNk+ANCR4PkLQ2wZBkyTUOayj0GEf/zQG6ueQxj/kanQ+GcsA3d+5BL5d3feRsYyYhu4U+T8+Di08ddoNHPNojX+nUmafyzPX8g+qrFWEQFfMUkkcd22U3DxacsiRp6IYJsEJ7ZFZFx+0mg0mrli0VqZeH49EHrcIsAbvz+OSPWsR2fWwpY1PVXHZfsHLftoNJoWsIiNf2hg4y2dhecvMI3kt0l09pwOdqylhHhdIF2ev0aj0cyExWv8EzV/XuRlUsTg15J9jBrH05CU/681f41Gc7JYtJp/xPOPVeMaFPX86xn5z/3mG3DqskLTrx9v+Qxoz1+j0Zw8FrHxr635WwbFWjbUNv7v3bqu5n31CCccdRKKBp41Go1mrli0VkZN9Yxv4B7X/Gci79Qik9Dzx+RtnbMpunpqNBrNTFi0VqYzwfNXUz1NM53nP13iE05wzEDOMkE0+6+n0Wg0KrNi/Ino40TEiKhPOXYTEe0hol1EdJVy/EIieoHf90VqkaXryNSu8DUNQoddnYUzm4j2D6rEYxg6x1+j0ZwcZmxpiGgdgCsAvK4c2wTgOgCbAVwN4BYiEtb0KwBuALCR/1w90zFMB9XzF7bdNILiK8sgnLuuV95vzsH8lEnq828YOtNHo9GcFGbDzfwCgD8FoPS2xDUAbmeMlRlj+wDsAbCNiFYB6GaMPcYYYwC+BeDaWRhD04iAr2VQRGbJWiZMg7B5dViYZc7Bdomh5x9dYehMH41GczKYkfEnoncDOMQYey521xoAB5S/D/Jja/jt+PFaz38DEW0nou2Dg4MzGWoVGSvYAzcu6WQtA6ZBQT8eEQCeA88/SfPP2ya6cos2AUuj0ZxEGloaIvoxgJUJd30SwJ8DuDLpYQnHWJ3jiTDGbgVwKwBs3bq15nnTpZC14MT68mQtQ6ZhXnBKLx5/dQhFx5vtl5YTi2r8P/H2s1FyZ/+1NBqNJk5D488YuzzpOBH9EoANAJ7jsslaAE8T0TYEHr2aAL8WwGF+fG3C8ZZQyFgY953IsdW9efR3BT17PvDL6/H4q0Po65z9vXKTPP/1fc0Xi2k0Gs10mLbGwBh7AcBy8TcR7QewlTF2nIjuBvAdIvobAKsRBHafYIx5RDRORBcD+AWADwD40kwuYCYUsmaVV3/bB7fJ6tt3/NIqbP/U5eibg71yrYRNXjQajeZkMScCM2NsJxHdAeBFAC6AGxljwsp+BMA3AeQB3MN/WkJHxoJpRD1/tfIXwJwYfiC5sZtGo9GcLGbN+DPG1sf+vhnAzQnnbQewZbZedyZ0Zq05KeBKQ1JjN41GozlZLGrLU8iac1LAlYakfv4ajUZzsljUeYUXnrqkZUVVWvbRaDStZFEb/xveenrLXlvLPhqNppVoy9Mikvr5azQazclCW54WoT1/jUbTSrTlaRG29vw1Gk0L0ZanRehsH41G00oWdcC3lfzauavQkTF1to9Go2kJ2vi3iDOWd+GM5V2tHoZGo1mkaM1Bo9FoFiHa+Gs0Gs0iRBt/jUajWYRo46/RaDSLEG38NRqNZhGijb9Go9EsQrTx12g0mkWINv4ajUazCCHGWKvHkAoiGgTw2jQf3gfg+CwOZ76jr3dho6934TIX13oqY6w/frBtjP9MIKLtjLGtrR7HyUJf78JGX+/C5WReq5Z9NBqNZhGijb9Go9EsQhaL8b+11QM4yejrXdjo6124nLRrXRSav0aj0WiiLBbPX6PRaDQK2vhrNBrNImRBG38iupqIdhHRHiL6RKvHMxcQ0X4ieoGIniWi7fzYUiK6n4h2899LWj3O6UJEXyeiASLaoRyreX1EdBP/vHcR0VWtGfX0qXG9nyGiQ/wzfpaI3qHc1+7Xu46IHiSil4hoJxH9IT++ID/jOtd78j9jxtiC/AFgAtgL4DQAGQDPAdjU6nHNwXXuB9AXO/Z/AHyC3/4EgL9q9ThncH1vBXABgB2Nrg/AJv45ZwFs4J+/2eprmIXr/QyAjyecuxCudxWAC/jtLgCv8OtakJ9xnes96Z/xQvb8twHYwxh7lTFWAXA7gGtaPKaTxTUAbuO3bwNwbeuGMjMYYw8BGIodrnV91wC4nTFWZoztA7AHwf9B21DjemuxEK73CGPsaX57HMBLANZggX7Gda63FnN2vQvZ+K8BcED5+yDqv8ntCgPwH0T0FBHdwI+tYIwdAYJ/NgDLWza6uaHW9S3kz/wPiOh5LgsJCWRBXS8RrQdwPoBfYBF8xrHrBU7yZ7yQjT8lHFuIea1vYoxdAODtAG4kore2ekAtZKF+5l8BcDqA8wAcAfDX/PiCuV4i6gRwJ4CPMcbG6p2acKztrjnhek/6Z7yQjf9BAOuUv9cCONyiscwZjLHD/PcAgO8hWBIeI6JVAMB/D7RuhHNCretbkJ85Y+wYY8xjjPkAvoZw2b8grpeIbASG8NuMsX/jhxfsZ5x0va34jBey8X8SwEYi2kBEGQDXAbi7xWOaVYioQERd4jaAKwHsQHCd1/PTrgdwV2tGOGfUur67AVxHRFki2gBgI4AnWjC+WUUYQc6vI/iMgQVwvUREAP4vgJcYY3+j3LUgP+Na19uSz7jV0e85jqy/A0E0fS+AT7Z6PHNwfachyAR4DsBOcY0AlgF4AMBu/ntpq8c6g2v8LoJlsIPAC/pQvesD8En+ee8C8PZWj3+WrvcfAbwA4HluDFYtoOt9MwIZ43kAz/KfdyzUz7jO9Z70z1i3d9BoNJpFyEKWfTQajUZTA238NRqNZhGijb9Go9EsQrTx12g0mkWINv4ajUazCNHGX6PRaBYh2vhrNBrNIuT/B/lvYW7EvoqBAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "def play_episode(env, agent, max_episode_steps=None, mode=None, render=False):\n",
    "    observation, reward, done = env.reset(), 0., False\n",
    "    agent.reset(mode=mode)\n",
    "    episode_reward, elapsed_steps = 0., 0\n",
    "    while True:\n",
    "        action = agent.step(observation, reward, done)\n",
    "        if render:\n",
    "            env.render()\n",
    "        if done:\n",
    "            break\n",
    "        observation, reward, done, _ = env.step(action)\n",
    "        episode_reward += reward\n",
    "        elapsed_steps += 1\n",
    "        if max_episode_steps and elapsed_steps >= max_episode_steps:\n",
    "            break\n",
    "    agent.close()\n",
    "    return episode_reward, elapsed_steps\n",
    "\n",
    "\n",
    "logging.info('==== train ====')\n",
    "episode_rewards = []\n",
    "for episode in itertools.count():\n",
    "    episode_reward, elapsed_steps = play_episode(env.unwrapped, agent,\n",
    "            max_episode_steps=env._max_episode_steps, mode='train')\n",
    "    episode_rewards.append(episode_reward)\n",
    "    logging.debug('train episode %d: reward = %.2f, steps = %d',\n",
    "            episode, episode_reward, elapsed_steps)\n",
    "    if np.mean(episode_rewards[-10:]) > 250:\n",
    "        break\n",
    "plt.plot(episode_rewards)\n",
    "\n",
    "\n",
    "logging.info('==== test ====')\n",
    "episode_rewards = []\n",
    "for episode in range(100):\n",
    "    episode_reward, elapsed_steps = play_episode(env, agent)\n",
    "    episode_rewards.append(episode_reward)\n",
    "    logging.debug('test episode %d: reward = %.2f, steps = %d',\n",
    "            episode, episode_reward, elapsed_steps)\n",
    "logging.info('average episode reward = %.2f ± %.2f',\n",
    "        np.mean(episode_rewards), np.std(episode_rewards))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
